diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ec50631166..9cb6bbbc14 100755 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -171,10 +171,6 @@ jobs: { "ID": "Build-Executor", "Args": ["state", "run", "build-exec"] - }, - { - "ID": "Build-MCP", - "Args": ["state", "run", "build-mcp"] } ] EOF @@ -230,11 +226,6 @@ jobs: shell: bash run: parallelize results Build-Executor - - # === "Build: MCP" === - name: "Build: MCP" - shell: bash - run: parallelize results Build-MCP - - # === Prepare Windows Cert === name: Prepare Windows Cert shell: bash @@ -255,7 +246,6 @@ jobs: signtool.exe sign -d "ActiveState State Service" -f "Cert.p12" -p ${CODE_SIGNING_PASSWD} ./build/state-svc.exe signtool.exe sign -d "ActiveState State Installer" -f "Cert.p12" -p ${CODE_SIGNING_PASSWD} ./build/state-installer.exe signtool.exe sign -d "ActiveState State Tool Remote Installer" -f "Cert.p12" -p ${CODE_SIGNING_PASSWD} ./build/state-remote-installer.exe - signtool.exe sign -d "ActiveState State MCP" -f "Cert.p12" -p ${CODE_SIGNING_PASSWD} ./build/state-mcp.exe env: CODE_SIGNING_PASSWD: ${{ secrets.CODE_SIGNING_PASSWD }} diff --git a/activestate.windows.yaml b/activestate.windows.yaml index 1ffd7363e7..76f5251757 100644 --- a/activestate.windows.yaml +++ b/activestate.windows.yaml @@ -7,8 +7,6 @@ constants: value: state-exec.exe - name: BUILD_INSTALLER_TARGET value: state-installer.exe - - name: BUILD_MCP_TARGET - value: state-mcp.exe - name: SVC_BUILDFLAGS value: -ldflags="-s -w -H=windowsgui" - name: SCRIPT_EXT diff --git a/activestate.yaml b/activestate.yaml index 896678ea01..cdc5b3183b 100644 --- a/activestate.yaml +++ b/activestate.yaml @@ -10,8 +10,6 @@ constants: value: ./cmd/state-installer - name: EXECUTOR_PKGS value: ./cmd/state-exec - - name: MCP_PKGS - value: ./cmd/state-mcp - name: BUILD_TARGET_PREFIX_DIR value: ./build - name: BUILD_TARGET @@ -31,9 +29,6 @@ constants: value: state-installer - name: BUILD_REMOTE_INSTALLER_TARGET value: state-remote-installer - - name: BUILD_MCP_TARGET - if: ne .OS.Name "Windows" - value: state-mcp - name: INTEGRATION_TEST_REGEX value: 'integration\|automation' - name: SET_ENV @@ -109,9 +104,7 @@ scripts: go generate popd > /dev/null fi - TARGET=$BUILD_TARGET_DIR/$constants.BUILD_TARGET - echo "Building $TARGET" - go build -tags "$GO_BUILD_TAGS" -o $TARGET $constants.CLI_BUILDFLAGS $constants.CLI_PKGS + go build -tags "$GO_BUILD_TAGS" -o $BUILD_TARGET_DIR/$constants.BUILD_TARGET $constants.CLI_BUILDFLAGS $constants.CLI_PKGS - name: build-svc language: bash standalone: true @@ -126,9 +119,7 @@ scripts: go generate popd > /dev/null fi - TARGET=$BUILD_TARGET_DIR/$constants.BUILD_DAEMON_TARGET - echo "Building $TARGET" - go build -tags "$GO_BUILD_TAGS" -o $TARGET $constants.SVC_BUILDFLAGS $constants.DAEMON_PKGS + go build -tags "$GO_BUILD_TAGS" -o $BUILD_TARGET_DIR/$constants.BUILD_DAEMON_TARGET $constants.SVC_BUILDFLAGS $constants.DAEMON_PKGS - name: build-exec description: Builds the State Executor application language: bash @@ -136,19 +127,8 @@ scripts: value: | set -e $constants.SET_ENV - TARGET=$BUILD_TARGET_DIR/$constants.BUILD_EXEC_TARGET - echo "Building $TARGET" - go build -tags "$GO_BUILD_TAGS" -o $TARGET $constants.CLI_BUILDFLAGS $constants.EXECUTOR_PKGS - - name: build-mcp - description: Builds the State MCP application - language: bash - standalone: true - value: | - set -e - $constants.SET_ENV - TARGET=$BUILD_TARGET_DIR/$constants.BUILD_MCP_TARGET - echo "Building $TARGET" - go build -tags "$GO_BUILD_TAGS" -o $TARGET $constants.CLI_BUILDFLAGS $constants.MCP_PKGS + + go build -tags "$GO_BUILD_TAGS" -o $BUILD_TARGET_DIR/$constants.BUILD_EXEC_TARGET $constants.CLI_BUILDFLAGS $constants.EXECUTOR_PKGS - name: build-all description: Builds all our tools language: bash @@ -165,8 +145,6 @@ scripts: $scripts.build-svc.path() echo "Building State Executor" $scripts.build-exec.path() - echo "Building State MCP" - $scripts.build-mcp.path() - name: build-installer language: bash standalone: true diff --git a/cmd/state-installer/cmd.go b/cmd/state-installer/cmd.go index 8bf68fbd73..89a5450319 100644 --- a/cmd/state-installer/cmd.go +++ b/cmd/state-installer/cmd.go @@ -475,7 +475,11 @@ func storeInstallSource(installSource string) { installSource = "state-installer" } - appData := storage.AppDataPath() + appData, err := storage.AppDataPath() + if err != nil { + multilog.Error("Could not store install source due to AppDataPath error: %s", errs.JoinMessage(err)) + return + } if err := fileutils.WriteFile(filepath.Join(appData, constants.InstallSourceFile), []byte(installSource)); err != nil { multilog.Error("Could not store install source due to WriteFile error: %s", errs.JoinMessage(err)) } diff --git a/cmd/state-mcp/internal/mcpserver/server.go b/cmd/state-mcp/internal/mcpserver/server.go deleted file mode 100644 index bb0a565c8a..0000000000 --- a/cmd/state-mcp/internal/mcpserver/server.go +++ /dev/null @@ -1,74 +0,0 @@ -package mcpserver - -import ( - "context" - "fmt" - - "github.com/ActiveState/cli/internal/constants" - "github.com/ActiveState/cli/internal/errs" - "github.com/ActiveState/cli/internal/logging" - "github.com/ActiveState/cli/internal/primer" - "github.com/mark3labs/mcp-go/mcp" - "github.com/mark3labs/mcp-go/server" -) - -type ToolHandlerFunc func(context.Context, *primer.Values, mcp.CallToolRequest) (*mcp.CallToolResult, error) - -// Handler wraps the MCP server and provides methods for adding tools and resources -type Handler struct { - Server *server.MCPServer - primeGetter func() (*primer.Values, func() error, error) -} - -func New(primeGetter func() (*primer.Values, func() error, error)) *Handler { - s := server.NewMCPServer( - constants.StateMCPCmd, - constants.VersionNumber, - ) - - mcpHandler := &Handler{ - Server: s, - primeGetter: primeGetter, - } - - return mcpHandler -} - -func (m Handler) ServeStdio() error { - if err := server.ServeStdio(m.Server); err != nil { - logging.Error("Server error: %v\n", err) - } - return nil -} - -// addResource adds a resource to the MCP server with error handling and logging -func (m *Handler) AddResource(resource mcp.Resource, handler server.ResourceHandlerFunc) { - m.Server.AddResource(resource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) { - r, err := handler(ctx, request) - if err != nil { - logging.Error("%s: Error handling resource request: %v", resource.Name, err) - return nil, errs.Wrap(err, "Failed to handle resource request") - } - return r, nil - }) -} - -// addTool adds a tool to the MCP server with error handling and logging -func (m *Handler) AddTool(tool mcp.Tool, handler ToolHandlerFunc) { - m.Server.AddTool(tool, func(ctx context.Context, request mcp.CallToolRequest) (r *mcp.CallToolResult, rerr error) { - p, closer, err := m.primeGetter() - if err != nil { - return nil, errs.Wrap(err, "Failed to get primer") - } - defer closer() - r, err = handler(ctx, p, request) - if err != nil { - logging.Error("%s: Error handling tool request: %v", tool.Name, errs.JoinMessage(err)) - // Format all errors as a single string, so the client gets the full context - return nil, fmt.Errorf("%s: %s", tool.Name, errs.JoinMessage(err)) - } - return r, nil - }) -} - - diff --git a/cmd/state-mcp/internal/toolregistry/categories.go b/cmd/state-mcp/internal/toolregistry/categories.go deleted file mode 100644 index 0960cd1d7f..0000000000 --- a/cmd/state-mcp/internal/toolregistry/categories.go +++ /dev/null @@ -1,23 +0,0 @@ -package toolregistry - -type ToolCategory string - -const ( - ToolCategoryDebug ToolCategory = "debug" -) - -type ToolCategories []ToolCategory - -func (c ToolCategories) String() []string { - result := []string{} - for _, category := range c { - result = append(result, string(category)) - } - return result -} - -func Categories() ToolCategories { - return ToolCategories{ - ToolCategoryDebug, - } -} \ No newline at end of file diff --git a/cmd/state-mcp/internal/toolregistry/registry.go b/cmd/state-mcp/internal/toolregistry/registry.go deleted file mode 100644 index 4592ccc2d5..0000000000 --- a/cmd/state-mcp/internal/toolregistry/registry.go +++ /dev/null @@ -1,56 +0,0 @@ -package toolregistry - -import ( - "context" - "slices" - - "github.com/ActiveState/cli/internal/primer" - "github.com/mark3labs/mcp-go/mcp" -) - -type Tool struct { - mcp.Tool - Category ToolCategory - Handler func(context.Context, *primer.Values, mcp.CallToolRequest) (*mcp.CallToolResult, error) -} - -type Registry struct { - tools map[ToolCategory][]Tool -} - -func New() *Registry { - r := &Registry{ - tools: make(map[ToolCategory][]Tool), - } - - r.RegisterTool(HelloWorldTool()) - - return r -} - -func (r *Registry) RegisterTool(tool Tool) { - if _, ok := r.tools[tool.Category]; !ok { - r.tools[tool.Category] = []Tool{} - } - r.tools[tool.Category] = append(r.tools[tool.Category], tool) -} - -func (r *Registry) GetTools(requestCategories ...string) []Tool { - if len(requestCategories) == 0 { - for _, category := range Categories() { - if category == ToolCategoryDebug { - // Debug must be explicitly requested - continue - } - requestCategories = append(requestCategories, string(category)) - } - } - categories := Categories() - result := []Tool{} - for _, category := range categories { - if slices.Contains(requestCategories, string(category)) { - result = append(result, r.tools[category]...) - } - } - return result -} \ No newline at end of file diff --git a/cmd/state-mcp/internal/toolregistry/tools.go b/cmd/state-mcp/internal/toolregistry/tools.go deleted file mode 100644 index 7b216bc7ae..0000000000 --- a/cmd/state-mcp/internal/toolregistry/tools.go +++ /dev/null @@ -1,40 +0,0 @@ -package toolregistry - -import ( - "context" - "strings" - - "github.com/ActiveState/cli/internal/primer" - "github.com/ActiveState/cli/internal/runners/hello" - "github.com/mark3labs/mcp-go/mcp" -) - -func HelloWorldTool() Tool { - return Tool{ - Category: ToolCategoryDebug, - Tool: mcp.NewTool( - "hello", - mcp.WithDescription("Hello world tool"), - mcp.WithString("name", mcp.Required(), mcp.Description("The name to say hello to")), - ), - Handler: func(ctx context.Context, p *primer.Values, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { - name, err := request.RequireString("name") - if err != nil { - return mcp.NewToolResultError(err.Error()), nil - } - - runner := hello.New(p) - params := hello.NewParams() - params.Name = name - - err = runner.Run(params) - if err != nil { - return mcp.NewToolResultError(err.Error()), nil - } - - return mcp.NewToolResultText( - strings.Join(p.Output().History().Print, "\n"), - ), nil - }, - } -} \ No newline at end of file diff --git a/cmd/state-mcp/main.go b/cmd/state-mcp/main.go deleted file mode 100644 index 0931ed11e4..0000000000 --- a/cmd/state-mcp/main.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "os" - "runtime/debug" - "strings" - "time" - - "github.com/ActiveState/cli/cmd/state-mcp/internal/mcpserver" - "github.com/ActiveState/cli/cmd/state-mcp/internal/toolregistry" - "github.com/ActiveState/cli/internal/events" - "github.com/ActiveState/cli/internal/logging" -) - -func main() { - defer func() { - logging.Debug("Exiting") - if r := recover(); r != nil { - logging.Error("Recovered from panic: %v", r) - fmt.Printf("Recovered from panic: %v, stack: %s\n", r, string(debug.Stack())) - os.Exit(1) - } - }() - defer func() { - if err := events.WaitForEvents(5*time.Second, logging.Close); err != nil { - logging.Warning("Failed waiting for events: %v", err) - } - }() - - // Parse command line flags - rawFlag := flag.String("categories", "", "Comma separated list of categories to register tools for") - flag.Parse() - - mcps := setupServer(strings.Split(*rawFlag, ",")...) - - // Start the stdio server - logging.Info("Starting MCP server") - if err := mcps.ServeStdio(); err != nil { - logging.Error("Server error: %v\n", err) - } -} - -func setupServer(categories ...string) *mcpserver.Handler { - mcps := mcpserver.New(newPrimer) - - registry := toolregistry.New() - tools := registry.GetTools(categories...) - for _, tool := range tools { - mcps.AddTool(tool.Tool, tool.Handler) - } - - return mcps -} diff --git a/cmd/state-mcp/primer.go b/cmd/state-mcp/primer.go deleted file mode 100644 index 5791b52ab6..0000000000 --- a/cmd/state-mcp/primer.go +++ /dev/null @@ -1,112 +0,0 @@ -package main - -import ( - "context" - "fmt" - "io" - "os" - "strings" - - "github.com/ActiveState/cli/internal/config" - "github.com/ActiveState/cli/internal/constraints" - "github.com/ActiveState/cli/internal/errs" - "github.com/ActiveState/cli/internal/installation" - "github.com/ActiveState/cli/internal/ipc" - "github.com/ActiveState/cli/internal/logging" - "github.com/ActiveState/cli/internal/multilog" - "github.com/ActiveState/cli/internal/output" - "github.com/ActiveState/cli/internal/primer" - "github.com/ActiveState/cli/internal/subshell" - "github.com/ActiveState/cli/internal/svcctl" - "github.com/ActiveState/cli/pkg/platform/authentication" - "github.com/ActiveState/cli/pkg/platform/model" - "github.com/ActiveState/cli/pkg/project" -) - -// newPrimer creates a new primer.Values instance for use with command execution -func newPrimer() (*primer.Values, func() error, error) { - closers := []func() error{} - closer := func() error { - for _, c := range closers { - if err := c(); err != nil { - return err - } - } - return nil - } - - cfg, err := config.New() - if err != nil { - return nil, closer, errs.Wrap(err, "Failed to create config") - } - closers = append(closers, cfg.Close) - - auth := authentication.New(cfg) - closers = append(closers, auth.Close) - - out, err := output.New(string(output.SimpleFormatName), &output.Config{ - OutWriter: io.Discard, // We use Outputer.History() instead - ErrWriter: io.Discard, // We use Outputer.History() instead - Colored: false, - Interactive: false, - ShellName: "", - }) - if err != nil { - return nil, closer, errs.Wrap(err, "Failed to create output") - } - - // Set up conditional, which accesses a lot of primer data - sshell := subshell.New(cfg) - - conditional := constraints.NewPrimeConditional(auth, nil, sshell.Shell()) - project.RegisterConditional(conditional) - if err := project.RegisterExpander("mixin", project.NewMixin(auth).Expander); err != nil { - logging.Debug("Could not register mixin expander: %v", err) - } - - ipcClient, svcPort, err := connectToSvc() - if err != nil { - return nil, closer, errs.Wrap(err, "Failed to connect to service") - } - - svcmodel := model.NewSvcModel(svcPort) - - if auth.AvailableAPIToken() != "" { - jwt, err := svcmodel.GetJWT(context.Background()) - if err != nil { - multilog.Critical("Could not get JWT: %v", errs.JoinMessage(err)) - } - if err != nil || jwt == nil { - // Could not authenticate; user got logged out - auth.Logout() - } else { - auth.UpdateSession(jwt) - } - } - - return primer.New(out, auth, sshell, conditional, cfg, ipcClient, svcmodel), closer, nil -} - - -type stdOutput struct{} - -func (s *stdOutput) Notice(msg interface{}) { - logging.Info(fmt.Sprintf("%v", msg)) -} - -// connectToSvc connects to the state service and returns an IPC client -func connectToSvc() (*ipc.Client, string, error) { - svcExec, err := installation.ServiceExec() - if err != nil { - return nil, "", errs.Wrap(err, "Could not get service info") - } - - ipcClient := svcctl.NewDefaultIPCClient() - argText := strings.Join(os.Args, " ") - svcPort, err := svcctl.EnsureExecStartedAndLocateHTTP(ipcClient, svcExec, argText, &stdOutput{}) - if err != nil { - return nil, "", errs.Wrap(err, "Failed to start state-svc at state tool invocation") - } - - return ipcClient, svcPort, nil -} \ No newline at end of file diff --git a/cmd/state-mcp/server_test.go b/cmd/state-mcp/server_test.go deleted file mode 100644 index 22807773d5..0000000000 --- a/cmd/state-mcp/server_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "context" - "encoding/json" - "testing" - - "github.com/ActiveState/cli/cmd/state-mcp/internal/toolregistry" - "github.com/ActiveState/cli/internal/logging" -) - -func TestServerHello(t *testing.T) { - t.Skip(` -Fails due to state-svc not being detected when run as regular test, -works when running with debugger. Problem for another day. -`) - logging.CurrentHandler().SetVerbose(true) - mcpHandler := setupServer(string(toolregistry.ToolCategoryDebug)) - msg := mcpHandler.Server.HandleMessage(context.Background(), json.RawMessage(`{ - "jsonrpc": "2.0", - "id": 1, - "method": "tools/call", - "params": { - "name": "hello", - "arguments": { - "name": "World" - } - } - }`)) - t.Fatalf("%+v", msg) -} diff --git a/go.mod b/go.mod index 9fa4dc87bc..d38fdb18c3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ActiveState/cli -go 1.23.7 +go 1.23.8 require ( github.com/99designs/gqlgen v0.17.54 @@ -9,6 +9,7 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 github.com/alecthomas/participle/v2 v2.0.0 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 + github.com/andygrunwald/go-jira v1.15.1 github.com/aws/aws-sdk-go v1.45.1 github.com/blang/semver v3.5.1+incompatible github.com/creack/pty v1.1.11 @@ -24,6 +25,7 @@ require ( github.com/go-openapi/swag v0.19.15 github.com/go-openapi/validate v0.20.2 github.com/gofrs/flock v0.8.1 + github.com/google/go-github/v45 v45.0.0 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.0 github.com/hashicorp/go-cleanhttp v0.5.2 @@ -43,20 +45,21 @@ require ( github.com/phayes/permbits v0.0.0-20190108233746-1efae4548023 github.com/posener/wstest v0.0.0-20180216222922-04b166ca0bf1 github.com/rollbar/rollbar-go v1.1.0 + github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 github.com/shirou/gopsutil/v3 v3.24.5 github.com/skratchdot/open-golang v0.0.0-20190104022628-a2dfa6d0dab6 - github.com/spf13/cast v1.9.2 + github.com/spf13/cast v1.3.0 github.com/spf13/cobra v1.1.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.10.0 github.com/thoas/go-funk v0.8.0 github.com/vbauerster/mpb/v7 v7.1.5 github.com/vektah/gqlparser/v2 v2.5.16 - golang.org/x/crypto v0.35.0 // indirect - golang.org/x/net v0.36.0 - golang.org/x/sys v0.30.0 - golang.org/x/term v0.29.0 - golang.org/x/text v0.22.0 + golang.org/x/crypto v0.37.0 // indirect + golang.org/x/net v0.39.0 + golang.org/x/sys v0.32.0 + golang.org/x/term v0.31.0 + golang.org/x/text v0.24.0 gopkg.in/AlecAivazis/survey.v1 v1.8.8 gopkg.in/toast.v1 v1.0.0-20180812000517-0a84660828b2 gopkg.in/yaml.v2 v2.4.0 @@ -73,7 +76,6 @@ require ( github.com/go-git/go-git/v5 v5.13.1 github.com/gowebpki/jcs v1.0.1 github.com/klauspost/compress v1.11.4 - github.com/mark3labs/mcp-go v0.33.0 github.com/mholt/archiver/v3 v3.5.1 github.com/zijiren233/yaml-comment v0.2.1 ) @@ -107,8 +109,7 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/skeema/knownhosts v1.3.0 // indirect github.com/sosodev/duration v1.3.1 // indirect - github.com/yosida95/uritemplate/v3 v3.0.2 // indirect - golang.org/x/sync v0.11.0 // indirect + golang.org/x/sync v0.13.0 // indirect ) require ( @@ -123,6 +124,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/emirpasic/gods v1.18.1 // indirect + github.com/fatih/structs v1.1.0 // indirect github.com/gammazero/deque v0.0.0-20200721202602-07291166fe33 // indirect github.com/go-openapi/analysis v0.20.0 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect @@ -131,7 +133,9 @@ require ( github.com/go-openapi/spec v0.20.3 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/golang-jwt/jwt/v4 v4.5.1 // indirect github.com/golang/snappy v0.0.4 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect @@ -160,6 +164,7 @@ require ( github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect + github.com/trivago/tgo v1.0.7 // indirect github.com/ulikunitz/xz v0.5.11 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.1 // indirect diff --git a/go.sum b/go.sum index c448786316..e8e9061cc9 100644 --- a/go.sum +++ b/go.sum @@ -68,6 +68,8 @@ github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSUL github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/andygrunwald/go-jira v1.15.1 h1:6J9aYKb9sW8bxv3pBLYBrs0wdsFrmGI5IeTgWSKWKc8= +github.com/andygrunwald/go-jira v1.15.1/go.mod h1:GIYN1sHOIsENWUZ7B4pDeT/nxEtrZpE8l0987O67ZR8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= @@ -151,10 +153,10 @@ github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FM github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/felixge/fgprof v0.9.0 h1:1Unx04fyC3gn3RMH/GuwUF1UdlulLMpJV13jr9SOHvs= github.com/felixge/fgprof v0.9.0/go.mod h1:7/HK6JFtFaARhIljgP2IV8rJLIoHDoOYoUphsnGvqxE= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gammazero/deque v0.0.0-20200721202602-07291166fe33 h1:UG4wNrJX9xSKnm/Gck5yTbxnOhpNleuE4MQRdmcGySo= @@ -307,6 +309,9 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= +github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -329,8 +334,13 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v45 v45.0.0 h1:LU0WBjYidxIVyx7PZeWb+FP4JZJ3Wh3FQgdumnGqiLs= +github.com/google/go-github/v45 v45.0.0/go.mod h1:FObaZJEDSTa/WGCzZ2Z3eoCDXWJKMenWWTrd8jrta28= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -462,8 +472,6 @@ github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7 github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mark3labs/mcp-go v0.33.0 h1:naxhjnTIs/tyPZmWUZFuG0lDmdA6sUyYGGf3gsHvTCc= -github.com/mark3labs/mcp-go v0.33.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ= @@ -594,6 +602,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= +github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 h1:Xuk8ma/ibJ1fOy4Ee11vHhUFHQNpHhrBneOCNHVXS5w= +github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7AwjWCpdPhkSmNAgUv5C7EJ4AbmjEB3r047r3DXWu3Y= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -618,9 +628,8 @@ github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERA github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= -github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= @@ -650,6 +659,8 @@ github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0h github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM= +github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= @@ -673,8 +684,6 @@ github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHM github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= -github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -717,6 +726,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= +golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= +golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -774,6 +785,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -788,6 +801,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -837,11 +852,16 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= +golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -853,6 +873,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= +golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= diff --git a/internal/analytics/client/sync/reporters/test.go b/internal/analytics/client/sync/reporters/test.go index 7fe70846b6..95ff0c426a 100644 --- a/internal/analytics/client/sync/reporters/test.go +++ b/internal/analytics/client/sync/reporters/test.go @@ -18,8 +18,10 @@ type TestReporter struct { const TestReportFilename = "analytics.log" func TestReportFilepath() string { - appdata := storage.AppDataPath() - logging.Warning("Appdata path: %s", appdata) + appdata, err := storage.AppDataPath() + if err != nil { + logging.Warning("Could not acquire appdata path, using cwd instead. Error received: %s", errs.JoinMessage(err)) + } return filepath.Join(appdata, TestReportFilename) } diff --git a/internal/captain/command.go b/internal/captain/command.go index 13288e04e9..16a25bc252 100644 --- a/internal/captain/command.go +++ b/internal/captain/command.go @@ -219,12 +219,9 @@ func (c *Command) ShortDescription() string { func (c *Command) Execute(args []string) error { defer profile.Measure("cobra:Execute", time.Now()) c.logArgs(args) - // Cobra always executes the root command, so we need to set the args for the root command - // This makes running command.Execute() super error-prone if the args don't match the command - // We should probably get rid of Cobra over issues like this - c.cobra.Root().SetArgs(args) - err := c.cobra.Root().Execute() - c.cobra.Root().SetArgs(nil) + c.cobra.SetArgs(args) + err := c.cobra.Execute() + c.cobra.SetArgs(nil) rationalizeError(&err) return setupSensibleErrors(err, args) } @@ -275,26 +272,15 @@ func (c *Command) Name() string { } func (c *Command) NameRecursive() string { - parent := c + child := c name := []string{} - for parent != nil { - name = append([]string{parent.Name()}, name...) - parent = parent.parent - if parent.parent == nil { - break // Don't include the root command in the name - } + for child != nil { + name = append([]string{child.Name()}, name...) + child = child.parent } return strings.Join(name, " ") } -func (c *Command) BaseCommand() *Command { - base := c - for base.parent != nil && base.parent.parent != nil { - base = base.parent - } - return base -} - func (c *Command) NamePadding() int { return c.cobra.NamePadding() } @@ -471,15 +457,6 @@ func (c *Command) Children() []*Command { return commands } -func (c *Command) AllChildren() []*Command { - commands := []*Command{} - for _, child := range c.Children() { - commands = append(commands, child) - commands = append(commands, child.AllChildren()...) - } - return commands -} - func (c *Command) AvailableChildren() []*Command { commands := []*Command{} for _, child := range c.Children() { diff --git a/internal/config/instance.go b/internal/config/instance.go index 05547ee13a..fd6d68fe48 100644 --- a/internal/config/instance.go +++ b/internal/config/instance.go @@ -41,10 +41,14 @@ func NewCustom(localPath string, thread *singlethread.Thread, closeThread bool) i.thread = thread i.closeThread = closeThread + var err error if localPath != "" { - i.appDataDir = storage.AppDataPathWithParent(localPath) + i.appDataDir, err = storage.AppDataPathWithParent(localPath) } else { - i.appDataDir = storage.AppDataPath() + i.appDataDir, err = storage.AppDataPath() + } + if err != nil { + return nil, errs.Wrap(err, "Could not detect appdata dir") } // Ensure appdata dir exists, because the sqlite driver sure doesn't @@ -57,7 +61,6 @@ func NewCustom(localPath string, thread *singlethread.Thread, closeThread bool) path := filepath.Join(i.appDataDir, C.InternalConfigFileName) - var err error t := time.Now() i.db, err = sql.Open("sqlite", path) if err != nil { @@ -219,11 +222,7 @@ func (i *Instance) AllKeys() []string { // GetStringMapStringSlice retrieves a map of string slices for a given key func (i *Instance) GetStringMapStringSlice(key string) map[string][]string { - v := cast.ToStringMapStringSlice(i.Get(key)) - if v == nil { - return map[string][]string{} - } - return v + return cast.ToStringMapStringSlice(i.Get(key)) } // GetBool retrieves a boolean value for a given key @@ -233,11 +232,7 @@ func (i *Instance) GetBool(key string) bool { // GetStringSlice retrieves a slice of strings for a given key func (i *Instance) GetStringSlice(key string) []string { - v := cast.ToStringSlice(i.Get(key)) - if v == nil { - return []string{} - } - return v + return cast.ToStringSlice(i.Get(key)) } // GetTime retrieves a time instance for a given key @@ -247,11 +242,7 @@ func (i *Instance) GetTime(key string) time.Time { // GetStringMap retrieves a map of strings to values for a given key func (i *Instance) GetStringMap(key string) map[string]interface{} { - v := cast.ToStringMap(i.Get(key)) - if v == nil { - return map[string]interface{}{} - } - return v + return cast.ToStringMap(i.Get(key)) } // ConfigPath returns the path at which our configuration is stored diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 29319a310a..da5104fe4b 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -436,9 +436,6 @@ const InstallerName = "State Installer" // StateExecutorCmd is the name of the state executor binary const StateExecutorCmd = "state-exec" -// StateMCPCmd is the name of the state mcp binary -const StateMCPCmd = "state-mcp" - // LegacyToplevelInstallArchiveDir is the top-level directory for files in an installation archive // This constant will be removed in DX-2081. const LegacyToplevelInstallArchiveDir = "state-install" diff --git a/internal/installation/appinfo.go b/internal/installation/appinfo.go index 0099891ad4..2a18a42e93 100644 --- a/internal/installation/appinfo.go +++ b/internal/installation/appinfo.go @@ -46,9 +46,7 @@ func newExecFromDir(baseDir string, exec executableType) (string, error) { // Work around dlv and goland debugger giving an unexpected executable path if !condition.BuiltViaCI() && len(os.Args) > 1 && - (strings.Contains(os.Args[0], "__debug_bin") || - strings.Contains(filepath.ToSlash(os.Args[0]), "GoLand/___") || - strings.Contains(os.Args[0], "go-build")) { + (strings.Contains(os.Args[0], "__debug_bin") || strings.Contains(filepath.ToSlash(os.Args[0]), "GoLand/___")) { rootPath := filepath.Clean(environment.GetRootPathUnsafe()) path = filepath.Join(rootPath, "build") } diff --git a/internal/installation/storage/storage.go b/internal/installation/storage/storage.go index f511f8d7c9..a8659cbed1 100644 --- a/internal/installation/storage/storage.go +++ b/internal/installation/storage/storage.go @@ -11,29 +11,12 @@ import ( "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/osutils/user" "github.com/google/uuid" + "github.com/shibukawa/configdir" ) +func AppDataPath() (string, error) { + configDirs := configdir.New(constants.InternalConfigNamespace, fmt.Sprintf("%s-%s", constants.LibraryName, constants.ChannelName)) -var homeDir string - -func init() { - var err error - homeDir, err = user.HomeDir() - if err != nil { - panic(fmt.Sprintf("Could not get home dir, you can fix this by ensuring the $HOME environment variable is set. Error: %v", err)) - } -} - - -func relativeAppDataPath() string { - return filepath.Join(constants.InternalConfigNamespace, fmt.Sprintf("%s-%s", constants.LibraryName, constants.ChannelName)) -} - -func relativeCachePath() string { - return constants.InternalConfigNamespace -} - -func AppDataPath() string { localPath, envSet := os.LookupEnv(constants.ConfigEnvVarName) if envSet { return AppDataPathWithParent(localPath) @@ -44,10 +27,35 @@ func AppDataPath() string { // panic as this only happening in tests panic(err) } - return localPath + return localPath, nil } - return AppDataPathWithParent(BaseAppDataPath()) + // Account for HOME dir not being set, meaning querying global folders will fail + // This is a workaround for docker envs that don't usually have $HOME set + _, envSet = os.LookupEnv("HOME") + if !envSet && runtime.GOOS != "windows" { + homeDir, err := user.HomeDir() + if err != nil { + if !condition.InUnitTest() { + return "", fmt.Errorf("Could not get user home directory: %w", err) + } + // Use temp dir if we're in a test (we don't want to write to our src directory) + var err error + localPath, err = os.MkdirTemp("", "cli-config-test") + if err != nil { + return "", fmt.Errorf("could not create temp dir: %w", err) + } + return AppDataPathWithParent(localPath) + } + os.Setenv("HOME", homeDir) + } + + dir := configDirs.QueryFolders(configdir.Global)[0].Path + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + return "", fmt.Errorf("could not create appdata dir: %s", dir) + } + + return dir, nil } var _appDataPathInTest string @@ -59,11 +67,11 @@ func appDataPathInTest() (string, error) { localPath, err := os.MkdirTemp("", "cli-config") if err != nil { - return "", fmt.Errorf("could not create temp dir: %w", err) + return "", fmt.Errorf("Could not create temp dir: %w", err) } err = os.RemoveAll(localPath) if err != nil { - return "", fmt.Errorf("could not remove generated config dir for tests: %w", err) + return "", fmt.Errorf("Could not remove generated config dir for tests: %w", err) } _appDataPathInTest = localPath @@ -71,15 +79,16 @@ func appDataPathInTest() (string, error) { return localPath, nil } -func AppDataPathWithParent(parentDir string) string { - dir := filepath.Join(parentDir, relativeAppDataPath()) +func AppDataPathWithParent(parentDir string) (string, error) { + configDirs := configdir.New(constants.InternalConfigNamespace, fmt.Sprintf("%s-%s", constants.LibraryName, constants.ChannelName)) + configDirs.LocalPath = parentDir + dir := configDirs.QueryFolders(configdir.Local)[0].Path + if err := os.MkdirAll(dir, os.ModePerm); err != nil { - // Can't use logging here because it would cause a circular dependency - // This would only happen if the user has corrupt permissions on their home dir - os.Stderr.WriteString(fmt.Sprintf("Could not create appdata dir: %s", dir)) + return "", fmt.Errorf("could not create appdata dir: %s", dir) } - return dir + return dir, nil } // CachePath returns the path at which our cache is stored @@ -99,15 +108,17 @@ func CachePath() string { cachePath = filepath.Join(drive, "temp", prefix+uuid.New().String()[0:8]) } } - return cachePath - - } - - if path := os.Getenv(constants.CacheEnvVarName); path != "" { - return path + } else if path := os.Getenv(constants.CacheEnvVarName); path != "" { + cachePath = path + } else { + cachePath = configdir.New(constants.InternalConfigNamespace, "").QueryCacheFolder().Path + if runtime.GOOS == "windows" { + // Explicitly append "cache" dir as the cachedir on Windows is the same as the local appdata dir (conflicts with config) + cachePath = filepath.Join(cachePath, "cache") + } } - return filepath.Join(BaseCachePath(), relativeCachePath()) + return cachePath } func GlobalBinDir() string { @@ -116,7 +127,11 @@ func GlobalBinDir() string { // InstallSource returns the installation source of the State Tool func InstallSource() (string, error) { - path := AppDataPath() + path, err := AppDataPath() + if err != nil { + return "", fmt.Errorf("Could not detect AppDataPath: %w", err) + } + installFilePath := filepath.Join(path, constants.InstallSourceFile) installFileData, err := os.ReadFile(installFilePath) if err != nil { diff --git a/internal/installation/storage/storage_darwin.go b/internal/installation/storage/storage_darwin.go deleted file mode 100644 index 2dde6e1630..0000000000 --- a/internal/installation/storage/storage_darwin.go +++ /dev/null @@ -1,13 +0,0 @@ -package storage - -import ( - "path/filepath" -) - -func BaseAppDataPath() string { - return filepath.Join(homeDir, "Library", "Application Support") -} - -func BaseCachePath() string { - return filepath.Join(homeDir, "Library", "Caches") -} diff --git a/internal/installation/storage/storage_test.go b/internal/installation/storage/storage_test.go index 6ecef193ad..d0887b59cf 100644 --- a/internal/installation/storage/storage_test.go +++ b/internal/installation/storage/storage_test.go @@ -4,10 +4,13 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func Test_AppDataPath(t *testing.T) { - path1 := AppDataPath() - path2 := AppDataPath() + path1, err := AppDataPath() + require.NoError(t, err) + path2, err := AppDataPath() + require.NoError(t, err) assert.Equal(t, path1, path2) } diff --git a/internal/installation/storage/storage_windows.go b/internal/installation/storage/storage_windows.go deleted file mode 100644 index 4a4986440a..0000000000 --- a/internal/installation/storage/storage_windows.go +++ /dev/null @@ -1,22 +0,0 @@ -package storage - -import ( - "os" - "path/filepath" -) - -func BaseAppDataPath() string { - if appData := os.Getenv("APPDATA"); appData != "" { - return appData - } - - return filepath.Join(homeDir, "AppData", "Roaming") -} - -func BaseCachePath() string { - if cache := os.Getenv("LOCALAPPDATA"); cache != "" { - return cache - } - - return filepath.Join(homeDir, "AppData", "Local", "cache") -} diff --git a/internal/installation/storage/storage_xdg.go b/internal/installation/storage/storage_xdg.go deleted file mode 100644 index 1efefd0649..0000000000 --- a/internal/installation/storage/storage_xdg.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build !windows && !darwin -// +build !windows,!darwin - -package storage - -import ( - "os" - "path/filepath" -) - -func BaseAppDataPath() string { - if os.Getenv("XDG_CONFIG_HOME") != "" { - return os.Getenv("XDG_CONFIG_HOME") - } - - return filepath.Join(homeDir, ".config") -} - -func BaseCachePath() string { - if os.Getenv("XDG_CACHE_HOME") != "" { - return os.Getenv("XDG_CACHE_HOME") - } - - return filepath.Join(homeDir, ".cache") -} diff --git a/internal/logging/defaults.go b/internal/logging/defaults.go index 395e41c446..68a5c897bf 100644 --- a/internal/logging/defaults.go +++ b/internal/logging/defaults.go @@ -83,7 +83,13 @@ func init() { defer func() { handlePanics(recover()) }() // Set up datadir - datadir = storage.AppDataPath() + var err error + datadir, err = storage.AppDataPath() + if err != nil { + log.SetOutput(os.Stderr) + Error("Could not detect AppData dir: %v", err) + return + } // Set up handler timestamp = time.Now().UnixNano() diff --git a/internal/osutils/user/user.go b/internal/osutils/user/user.go index e8238c3063..1b485d0fab 100644 --- a/internal/osutils/user/user.go +++ b/internal/osutils/user/user.go @@ -2,10 +2,8 @@ package user import ( "os" - "os/user" "github.com/ActiveState/cli/internal/constants" - "github.com/ActiveState/cli/internal/errs" ) // HomeDirNotFoundError is an error that implements the ErrorLocalier and ErrorInput interfaces @@ -42,16 +40,9 @@ func HomeDir() (string, error) { if dir := os.Getenv(constants.HomeEnvVarName); dir != "" { return dir, nil } - - u, err := user.Current() - if err == nil { - return u.HomeDir, nil - } - - // If we can't get the current user, try to get the home dir from the os - dir, err2 := os.UserHomeDir() - if err2 != nil { - return "", &HomeDirNotFoundError{errs.Pack(err, err2)} + dir, err := os.UserHomeDir() + if err != nil { + return "", &HomeDirNotFoundError{err} } return dir, nil } diff --git a/internal/osutils/user/user_test.go b/internal/osutils/user/user_test.go index 9a487750a4..27c5010622 100644 --- a/internal/osutils/user/user_test.go +++ b/internal/osutils/user/user_test.go @@ -39,5 +39,6 @@ func TestNoHome(t *testing.T) { defer func() { os.Setenv("USERPROFILE", osHomeDir) }() } _, err = HomeDir() - assert.NoError(t, err) + assert.Error(t, err) + assert.Contains(t, err.Error(), "HOME environment variable is unset") } diff --git a/internal/output/json.go b/internal/output/json.go index a7dbc41eda..ad2b8e2939 100644 --- a/internal/output/json.go +++ b/internal/output/json.go @@ -19,12 +19,11 @@ import ( type JSON struct { cfg *Config wroteOutput bool - history *OutputHistory } // NewJSON constructs a new JSON struct func NewJSON(config *Config) (JSON, error) { - return JSON{cfg: config, history: &OutputHistory{}}, nil + return JSON{cfg: config}, nil } // Type tells callers what type of outputer we are @@ -39,11 +38,7 @@ func (f *JSON) Print(v interface{}) { return } - w := NewWriteProxy(f.cfg.OutWriter, func(p []byte) { - f.history.Print = append(f.history.Print, string(p)) - }) - - f.Fprint(w, v) + f.Fprint(f.cfg.OutWriter, v) } // Fprint allows printing to a specific writer, using all the conveniences of the output package @@ -102,11 +97,7 @@ func (f *JSON) Error(value interface{}) { } b = []byte(colorize.StripColorCodes(string(b))) - w := NewWriteProxy(f.cfg.OutWriter, func(p []byte) { - f.history.Error = append(f.history.Error, string(p)) - }) - - _, err = w.Write(b) + _, err = f.cfg.OutWriter.Write(b) if err != nil { if isPipeClosedError(err) { logging.Error("Could not write json output, error: %v", err) // do not log to rollbar @@ -116,10 +107,6 @@ func (f *JSON) Error(value interface{}) { } } -func (f *JSON) History() *OutputHistory { - return f.history -} - func isPipeClosedError(err error) bool { pipeErr := errors.Is(err, syscall.EPIPE) if runtime.GOOS == "windows" && errors.Is(err, syscall.Errno(232)) { diff --git a/internal/output/json_test.go b/internal/output/json_test.go index 2f42dbe290..3c6e1deef1 100644 --- a/internal/output/json_test.go +++ b/internal/output/json_test.go @@ -7,7 +7,6 @@ import ( "github.com/ActiveState/cli/internal/locale" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestJSON_Print(t *testing.T) { @@ -66,13 +65,12 @@ func TestJSON_Print(t *testing.T) { outWriter := &bytes.Buffer{} errWriter := &bytes.Buffer{} - f, err := NewJSON(&Config{ + f := &JSON{cfg: &Config{ OutWriter: outWriter, ErrWriter: errWriter, Colored: false, Interactive: false, - }) - require.NoError(t, err) + }} f.Print(tt.args.value) assert.Equal(t, tt.expectedOut, outWriter.String(), "Output did not match") @@ -103,13 +101,12 @@ func TestJSON_Notice(t *testing.T) { outWriter := &bytes.Buffer{} errWriter := &bytes.Buffer{} - f, err := NewJSON(&Config{ + f := &JSON{cfg: &Config{ OutWriter: outWriter, ErrWriter: errWriter, Colored: false, Interactive: false, - }) - require.NoError(t, err) + }} f.Notice(tt.args.value) assert.Equal(t, tt.expectedOut, outWriter.String(), "Output did not match") @@ -158,13 +155,12 @@ func TestJSON_Error(t *testing.T) { outWriter := &bytes.Buffer{} errWriter := &bytes.Buffer{} - f, err := NewJSON(&Config{ + f := &JSON{cfg: &Config{ OutWriter: outWriter, ErrWriter: errWriter, Colored: false, Interactive: false, - }) - require.NoError(t, err) + }} f.Error(tt.args.value) assert.Equal(t, tt.expectedOut, outWriter.String(), "Output did not match") diff --git a/internal/output/mediator.go b/internal/output/mediator.go index fbc0cac065..4dd71a69a8 100644 --- a/internal/output/mediator.go +++ b/internal/output/mediator.go @@ -52,10 +52,6 @@ func (m *Mediator) Notice(v interface{}) { m.Outputer.Notice(v) } -func (m *Mediator) History() *OutputHistory { - return m.Outputer.History() -} - func mediatorValue(v interface{}, format Format) interface{} { if format.IsStructured() { if vt, ok := v.(StructuredMarshaller); ok { diff --git a/internal/output/output.go b/internal/output/output.go index 282cd50125..529f2cea3c 100644 --- a/internal/output/output.go +++ b/internal/output/output.go @@ -29,12 +29,6 @@ const ( var ErrNotRecognized = errs.New("Not Recognized") -type OutputHistory struct { - Print []string - Error []string - Notice []string -} - // Outputer is the initialized formatter type Outputer interface { Fprint(writer io.Writer, value interface{}) @@ -43,7 +37,6 @@ type Outputer interface { Notice(value interface{}) Type() Format Config() *Config - History() *OutputHistory } // lastCreated is here for specific legacy use cases diff --git a/internal/output/plain.go b/internal/output/plain.go index c810dc330f..14e8088bbb 100644 --- a/internal/output/plain.go +++ b/internal/output/plain.go @@ -49,12 +49,11 @@ const ( // Struct keys are localized by sending them to the locale library as field_key (lowercase) type Plain struct { cfg *Config - history *OutputHistory`` } // NewPlain constructs a new Plain struct func NewPlain(config *Config) (Plain, error) { - return Plain{cfg: config, history: &OutputHistory{}}, nil + return Plain{config}, nil } // Type tells callers what type of outputer we are @@ -69,29 +68,20 @@ func (f *Plain) Fprint(writer io.Writer, v interface{}) { // Print will marshal and print the given value to the output writer func (f *Plain) Print(value interface{}) { - w := NewWriteProxy(f.cfg.OutWriter, func(p []byte) { - f.history.Print = append(f.history.Print, string(p)) - }) - f.write(w, value) - f.write(w, "\n") + f.write(f.cfg.OutWriter, value) + f.write(f.cfg.OutWriter, "\n") } // Error will marshal and print the given value to the error writer, it wraps it in the error format but otherwise the // only thing that identifies it as an error is the channel it writes it to func (f *Plain) Error(value interface{}) { - w := NewWriteProxy(f.cfg.ErrWriter, func(p []byte) { - f.history.Error = append(f.history.Error, string(p)) - }) - f.write(w, fmt.Sprintf("[ERROR]%s[/RESET]\n", value)) + f.write(f.cfg.ErrWriter, fmt.Sprintf("[ERROR]%s[/RESET]\n", value)) } // Notice will marshal and print the given value to the error writer, it wraps it in the notice format but otherwise the // only thing that identifies it as an error is the channel it writes it to func (f *Plain) Notice(value interface{}) { - w := NewWriteProxy(f.cfg.ErrWriter, func(p []byte) { - f.history.Notice = append(f.history.Notice, string(p)) - }) - f.write(w, fmt.Sprintf("%s\n", value)) + f.write(f.cfg.ErrWriter, fmt.Sprintf("%s\n", value)) } // Config returns the Config struct for the active instance @@ -99,10 +89,6 @@ func (f *Plain) Config() *Config { return f.cfg } -func (f *Plain) History() *OutputHistory { - return f.history -} - // write is a little helper that just takes care of marshalling the value and sending it to the requested writer func (f *Plain) write(writer io.Writer, value interface{}) { v, err := sprint(value, nil) diff --git a/internal/output/plain_test.go b/internal/output/plain_test.go index c80ac212ed..836e8c0947 100644 --- a/internal/output/plain_test.go +++ b/internal/output/plain_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func nilStr(s string) *string { @@ -239,13 +238,12 @@ func TestPlain_Print(t *testing.T) { outWriter := &bytes.Buffer{} errWriter := &bytes.Buffer{} - f, err := NewPlain(&Config{ + f := &Plain{&Config{ OutWriter: outWriter, ErrWriter: errWriter, Colored: false, Interactive: false, - }) - require.NoError(t, err) + }} f.Print(tt.args.value) assert.Equal(t, tt.expectedOut, outWriter.String(), "Output did not match") @@ -276,13 +274,12 @@ func TestPlain_Notice(t *testing.T) { outWriter := &bytes.Buffer{} errWriter := &bytes.Buffer{} - f, err := NewPlain(&Config{ + f := &Plain{&Config{ OutWriter: outWriter, ErrWriter: errWriter, Colored: false, Interactive: false, - }) - require.NoError(t, err) + }} f.Notice(tt.args.value) assert.Equal(t, tt.expectedOut, outWriter.String(), "Output did not match") @@ -313,13 +310,12 @@ func TestPlain_Error(t *testing.T) { outWriter := &bytes.Buffer{} errWriter := &bytes.Buffer{} - f, err := NewPlain(&Config{ + f := &Plain{&Config{ OutWriter: outWriter, ErrWriter: errWriter, Colored: false, Interactive: false, - }) - require.NoError(t, err) + }} f.Error(tt.args.value) assert.Equal(t, tt.expectedOut, outWriter.String(), "Output did not match") diff --git a/internal/output/simple_test.go b/internal/output/simple_test.go index 48fa099fe2..143d084ebf 100644 --- a/internal/output/simple_test.go +++ b/internal/output/simple_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestSimple_Notice(t *testing.T) { @@ -30,13 +29,12 @@ func TestSimple_Notice(t *testing.T) { outWriter := &bytes.Buffer{} errWriter := &bytes.Buffer{} - f, err := NewSimple(&Config{ + f := Simple{Plain{&Config{ OutWriter: outWriter, ErrWriter: errWriter, Colored: false, Interactive: false, - }) - require.NoError(t, err) + }}} f.Notice(tt.args.value) assert.Equal(t, tt.expectedOut, outWriter.String(), "Output did not match") diff --git a/internal/output/writer.go b/internal/output/writer.go deleted file mode 100644 index 6613dd6605..0000000000 --- a/internal/output/writer.go +++ /dev/null @@ -1,17 +0,0 @@ -package output - -import "io" - -type WriteProxy struct { - w io.Writer - onWrite func(p []byte) -} - -func NewWriteProxy(w io.Writer, onWrite func(p []byte)) *WriteProxy { - return &WriteProxy{w: w, onWrite: onWrite} -} - -func (w *WriteProxy) Write(p []byte) (n int, err error) { - w.onWrite(p) - return w.w.Write(p) -} \ No newline at end of file diff --git a/internal/runners/cve/cve.go b/internal/runners/cve/cve.go index 03739140cd..96c24a24f4 100644 --- a/internal/runners/cve/cve.go +++ b/internal/runners/cve/cve.go @@ -71,7 +71,7 @@ func (r *Cve) Run(params *Params) error { ) } - vulnerabilities, err := r.fetchVulnerabilities(params.Namespace) + vulnerabilities, err := r.fetchVulnerabilities(*params.Namespace) if err != nil { var errProjectNotFound *model.ErrProjectNotFound if errors.As(err, &errProjectNotFound) { @@ -101,7 +101,7 @@ func (r *Cve) Run(params *Params) error { return nil } -func (r *Cve) fetchVulnerabilities(namespaceOverride *project.Namespaced) (*medmodel.CommitVulnerabilities, error) { +func (r *Cve) fetchVulnerabilities(namespaceOverride project.Namespaced) (*medmodel.CommitVulnerabilities, error) { if namespaceOverride.IsValid() && namespaceOverride.CommitID == nil { resp, err := model.FetchProjectVulnerabilities(r.auth, namespaceOverride.Owner, namespaceOverride.Project) if err != nil { @@ -135,6 +135,9 @@ type SeverityCountOutput struct { } func (rd *cveOutput) MarshalOutput(format output.Format) interface{} { + if format != output.PlainFormatName { + return rd.data + } ri := &CveInfo{ fmt.Sprintf("[ACTIONABLE]%s[/RESET]", rd.data.Project), rd.data.CommitID, diff --git a/internal/runners/hello/hello_example.go b/internal/runners/hello/hello_example.go index b8cbe22bc0..a13ee016c3 100644 --- a/internal/runners/hello/hello_example.go +++ b/internal/runners/hello/hello_example.go @@ -10,13 +10,16 @@ package hello import ( "errors" - "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/primer" "github.com/ActiveState/cli/internal/runbits/example" + "github.com/ActiveState/cli/internal/runbits/rationalize" + "github.com/ActiveState/cli/pkg/localcommit" "github.com/ActiveState/cli/pkg/platform/authentication" + "github.com/ActiveState/cli/pkg/platform/model" + "github.com/ActiveState/cli/pkg/project" ) // primeable describes the app-level dependencies that a runner will need. @@ -46,6 +49,7 @@ func NewParams() *Params { // function. type Hello struct { out output.Outputer + project *project.Project auth *authentication.Auth } @@ -54,6 +58,7 @@ type Hello struct { func New(p primeable) *Hello { return &Hello{ out: p.Output(), + project: p.Project(), auth: p.Auth(), } } @@ -72,6 +77,15 @@ func rationalizeError(err *error) { // Ensure we wrap the top-level error returned from the runner and not // the unpacked error that we are inspecting. *err = errs.WrapUserFacing(*err, locale.Tl("hello_err_no_name", "Cannot say hello because no name was provided.")) + case errors.Is(*err, rationalize.ErrNoProject): + // It's useful to offer users reasonable tips on recourses. + *err = errs.WrapUserFacing( + *err, + locale.Tl("hello_err_no_project", "Cannot say hello because you are not in a project directory."), + errs.SetTips( + locale.Tl("hello_suggest_checkout", "Try using '[ACTIONABLE]state checkout[/RESET]' first."), + ), + ) } } @@ -81,6 +95,10 @@ func (h *Hello) Run(params *Params) (rerr error) { h.out.Print(locale.Tl("hello_notice", "This command is for example use only")) + if h.project == nil { + return rationalize.ErrNoProject + } + // Reusable runner logic is contained within the runbits package. // You should only use this if you intend to share logic between // runners. Runners should NEVER invoke other runners. @@ -102,11 +120,50 @@ func (h *Hello) Run(params *Params) (rerr error) { return nil } + // Grab data from the platform. + commitMsg, err := currentCommitMessage(h.project, h.auth) + if err != nil { + err = errs.Wrap( + err, "Cannot get commit message", + ) + return errs.AddTips( + err, + locale.Tl("hello_info_suggest_ensure_commit", "Ensure project has commits"), + ) + } + h.out.Print(locale.Tl( "hello_extra_info", - "You are on commit {{.V0}}", - constants.RevisionHashShort, + "Project: {{.V0}}\nCurrent commit message: {{.V1}}", + h.project.Namespace().String(), commitMsg, )) return nil -} \ No newline at end of file +} + +// currentCommitMessage contains the scope in which the current commit message +// is obtained. Since it is a sort of construction function that has some +// complexity, it is helpful to provide localized error context. Secluding this +// sort of logic is helpful to keep the subhandlers clean. +func currentCommitMessage(proj *project.Project, auth *authentication.Auth) (string, error) { + if proj == nil { + return "", errs.New("Cannot determine which project to use") + } + + commitId, err := localcommit.Get(proj.Dir()) + if err != nil { + return "", errs.Wrap(err, "Cannot determine which commit to use") + } + + commit, err := model.GetCommit(commitId, auth) + if err != nil { + return "", errs.Wrap(err, "Cannot get commit from server") + } + + commitMsg := locale.Tl("hello_info_warn_no_commit", "Commit description not provided.") + if commit.Message != "" { + commitMsg = commit.Message + } + + return commitMsg, nil +} diff --git a/internal/svcctl/svcctl.go b/internal/svcctl/svcctl.go index 0887749d85..58933826f9 100644 --- a/internal/svcctl/svcctl.go +++ b/internal/svcctl/svcctl.go @@ -7,19 +7,21 @@ package svcctl import ( "context" "errors" + "fmt" "io" "os" + "path/filepath" "time" "github.com/ActiveState/cli/internal/constants" "github.com/ActiveState/cli/internal/errs" "github.com/ActiveState/cli/internal/fileutils" "github.com/ActiveState/cli/internal/installation" - "github.com/ActiveState/cli/internal/installation/storage" "github.com/ActiveState/cli/internal/ipc" "github.com/ActiveState/cli/internal/locale" "github.com/ActiveState/cli/internal/logging" "github.com/ActiveState/cli/internal/osutils" + "github.com/ActiveState/cli/internal/output" "github.com/ActiveState/cli/internal/profile" ) @@ -43,30 +45,25 @@ type IPCommunicator interface { SockPath() *ipc.SockPath } -type Outputer interface { - Notice(interface{}) -} - func NewIPCSockPathFromGlobals() *ipc.SockPath { - rootDir := storage.AppDataPath() + subdir := fmt.Sprintf("%s-%s", constants.CommandName, "ipc") + rootDir := filepath.Join(os.TempDir(), subdir) if os.Getenv(constants.ServiceSockDir) != "" { rootDir = os.Getenv(constants.ServiceSockDir) } - sp := &ipc.SockPath{ + return &ipc.SockPath{ RootDir: rootDir, AppName: constants.CommandName, AppChannel: constants.ChannelName, } - - return sp } func NewDefaultIPCClient() *ipc.Client { return ipc.NewClient(NewIPCSockPathFromGlobals()) } -func EnsureExecStartedAndLocateHTTP(ipComm IPCommunicator, exec, argText string, out Outputer) (addr string, err error) { +func EnsureExecStartedAndLocateHTTP(ipComm IPCommunicator, exec, argText string, out output.Outputer) (addr string, err error) { defer profile.Measure("svcctl:EnsureExecStartedAndLocateHTTP", time.Now()) addr, err = LocateHTTP(ipComm) @@ -94,7 +91,7 @@ func EnsureExecStartedAndLocateHTTP(ipComm IPCommunicator, exec, argText string, return addr, nil } -func EnsureStartedAndLocateHTTP(argText string, out Outputer) (addr string, err error) { +func EnsureStartedAndLocateHTTP(argText string, out output.Outputer) (addr string, err error) { svcExec, err := installation.ServiceExec() if err != nil { return "", locale.WrapError(err, "err_service_exec") @@ -149,7 +146,7 @@ func StopServer(ipComm IPCommunicator) error { return nil } -func startAndWait(ctx context.Context, ipComm IPCommunicator, exec, argText string, out Outputer) error { +func startAndWait(ctx context.Context, ipComm IPCommunicator, exec, argText string, out output.Outputer) error { defer profile.Measure("svcmanager:Start", time.Now()) if !fileutils.FileExists(exec) { @@ -177,7 +174,7 @@ var ( waitTimeoutL10nKey = "svcctl_wait_timeout" ) -func waitUp(ctx context.Context, ipComm IPCommunicator, out Outputer, debugInfo *debugData) error { +func waitUp(ctx context.Context, ipComm IPCommunicator, out output.Outputer, debugInfo *debugData) error { debugInfo.startWait() defer debugInfo.stopWait() diff --git a/internal/testhelpers/outputhelper/outputer.go b/internal/testhelpers/outputhelper/outputer.go index 7e0bdb30c9..18a9b30da2 100644 --- a/internal/testhelpers/outputhelper/outputer.go +++ b/internal/testhelpers/outputhelper/outputer.go @@ -14,4 +14,3 @@ func (o *TestOutputer) Fprint(w io.Writer, value interface{}) {} func (o *TestOutputer) Error(value interface{}) {} func (o *TestOutputer) Notice(value interface{}) {} func (o *TestOutputer) Config() *output.Config { return nil } -func (o *TestOutputer) History() *output.OutputHistory { return nil } \ No newline at end of file diff --git a/internal/updater/updater.go b/internal/updater/updater.go index 3560ae1557..bd2a661cb0 100644 --- a/internal/updater/updater.go +++ b/internal/updater/updater.go @@ -207,7 +207,10 @@ func (u *UpdateInstaller) InstallBlocking(installTargetPath string, args ...stri return errs.Wrap(err, "Could not check if State Tool was installed as admin") } - appdata := storage.AppDataPath() + appdata, err := storage.AppDataPath() + if err != nil { + return errs.Wrap(err, "Could not detect appdata path") + } // Protect against multiple updates happening simultaneously lockFile := filepath.Join(appdata, "install.lock") diff --git a/pkg/platform/model/svc.go b/pkg/platform/model/svc.go index 43e7bcebc3..d6e4af9ae3 100644 --- a/pkg/platform/model/svc.go +++ b/pkg/platform/model/svc.go @@ -181,6 +181,7 @@ func (m *SvcModel) GetProcessesInUse(ctx context.Context, execDir string) ([]*gr // Note we respond with mono_models.JWT here for compatibility and to minimize the changeset at time of implementation. // We can revisit this in the future. func (m *SvcModel) GetJWT(ctx context.Context) (*mono_models.JWT, error) { + logging.Debug("Checking for GetJWT") defer profile.Measure("svc:GetJWT", time.Now()) r := request.NewJWTRequest() diff --git a/pkg/projectfile/projectfile.go b/pkg/projectfile/projectfile.go index 3879d816e2..e3ebcc5c62 100644 --- a/pkg/projectfile/projectfile.go +++ b/pkg/projectfile/projectfile.go @@ -1129,7 +1129,7 @@ func AddLockInfo(projectFilePath, branch, version string) error { projectRegex := regexp.MustCompile(fmt.Sprintf("(?m:(^project:\\s*%s))", ProjectURLRe)) lockString := fmt.Sprintf("%s@%s", branch, version) - lockUpdate := []byte(fmt.Sprintf(`${1}\nlock: %s`, lockString)) + lockUpdate := []byte(fmt.Sprintf("${1}\nlock: %s", lockString)) data, err = os.ReadFile(projectFilePath) if err != nil { @@ -1263,9 +1263,6 @@ func addDeprecatedProjectMappings(cfg ConfigGetter) { if err != nil && v != nil { // don't report if error due to nil input multilog.Log(logging.ErrorNoStacktrace, rollbar.Error)("Projects data in config is abnormal (type: %T)", v) } - if projects == nil { - projects = map[string][]string{} - } keys := funk.FilterString(cfg.AllKeys(), func(v string) bool { return strings.HasPrefix(v, "project_") @@ -1319,9 +1316,6 @@ func StoreProjectMapping(cfg ConfigGetter, namespace, projectPath string) { if err != nil && v != nil { // don't report if error due to nil input multilog.Log(logging.ErrorNoStacktrace, rollbar.Error)("Projects data in config is abnormal (type: %T)", v) } - if projects == nil { - projects = make(map[string][]string) - } projectPath, err = fileutils.ResolveUniquePath(projectPath) if err != nil { @@ -1376,9 +1370,6 @@ func CleanProjectMapping(cfg ConfigGetter) { if err != nil && v != nil { // don't report if error due to nil input multilog.Log(logging.ErrorNoStacktrace, rollbar.Error)("Projects data in config is abnormal (type: %T)", v) } - if projects == nil { - projects = make(map[string][]string) - } seen := make(map[string]struct{}) diff --git a/scripts/ci/parallelize/parallelize.go b/scripts/ci/parallelize/parallelize.go index fe135e2b63..f963523645 100644 --- a/scripts/ci/parallelize/parallelize.go +++ b/scripts/ci/parallelize/parallelize.go @@ -68,7 +68,10 @@ func run() error { } func jobDir() string { - path := storage.AppDataPath() + path, err := storage.AppDataPath() + if err != nil { + panic(err) + } path = filepath.Join(path, "jobs") if err := fileutils.MkdirUnlessExists(path); err != nil { diff --git a/scripts/ci/payload-generator/main.go b/scripts/ci/payload-generator/main.go index d50e1bd235..d264c37853 100644 --- a/scripts/ci/payload-generator/main.go +++ b/scripts/ci/payload-generator/main.go @@ -71,7 +71,6 @@ func generatePayload(inDir, outDir, binDir, channel, version string) error { filepath.Join(inDir, constants.StateCmd+osutils.ExeExtension): binDir, filepath.Join(inDir, constants.StateSvcCmd+osutils.ExeExtension): binDir, filepath.Join(inDir, constants.StateExecutorCmd+osutils.ExeExtension): binDir, - filepath.Join(inDir, constants.StateMCPCmd+osutils.ExeExtension): binDir, } if err := copyFiles(files); err != nil { return fmt.Errorf(emsg, err) @@ -108,7 +107,6 @@ func copyFiles(files map[string]string) error { dest := filepath.Join(target, filepath.Base(src)) if err := fileutils.CopyFile(src, dest); err != nil { - fmt.Printf("Files in %s: %+v\n", filepath.Dir(src), fileutils.ListFilesUnsafe(filepath.Dir(src))) return fmt.Errorf("copy files (%s to %s): %w", src, target, err) } } diff --git a/test/integration/performance_svc_int_test.go b/test/integration/performance_svc_int_test.go index 46f0ecf20d..5d05fa7615 100644 --- a/test/integration/performance_svc_int_test.go +++ b/test/integration/performance_svc_int_test.go @@ -41,7 +41,9 @@ func (suite *PerformanceIntegrationTestSuite) TestSvcPerformance() { // This integration test is a bit special because it bypasses the spawning logic // so in order to get the right log files when debugging we manually provide the config dir - ts.Dirs.Config = storage.AppDataPath() + var err error + ts.Dirs.Config, err = storage.AppDataPath() + suite.Require().NoError(err) ipcClient := svcctl.NewDefaultIPCClient() var svcPort string diff --git a/vendor/github.com/andygrunwald/go-jira/.gitignore b/vendor/github.com/andygrunwald/go-jira/.gitignore new file mode 100644 index 0000000000..e200606201 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/.gitignore @@ -0,0 +1,30 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Don't check in vendor +vendor/ + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +*.iml +.idea +.DS_Store \ No newline at end of file diff --git a/vendor/github.com/andygrunwald/go-jira/CHANGELOG.md b/vendor/github.com/andygrunwald/go-jira/CHANGELOG.md new file mode 100644 index 0000000000..5915ef4324 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/CHANGELOG.md @@ -0,0 +1,104 @@ +# Changelog + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## [1.13.0](https://github.com/andygrunwald/go-jira/compare/v1.11.1...v1.13.0) (2020-10-25) + + +### Features + +* add AddRemoteLink method ([f200e15](https://github.com/andygrunwald/go-jira/commit/f200e158b997a303db081cbbc5a9d8ad5d89566d)), closes [/developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2](https://github.com/andygrunwald//developer.atlassian.com/cloud/jira/platform/rest/v2//issues/api-rest-api-2) +* Add Names support on Issue struct ([#278](https://github.com/andygrunwald/go-jira/issues/278)) ([1fc10e0](https://github.com/andygrunwald/go-jira/commit/1fc10e0606784f745673ccc4d8d706c36f385a7a)) +* Extend Makefile for more source code quality targets ([5e52236](https://github.com/andygrunwald/go-jira/commit/5e5223631a29d10a13e598318a6abe47384e2982)) +* **context:** Add support for context package ([e1f4265](https://github.com/andygrunwald/go-jira/commit/e1f4265e2b467b938fe0c095caf6d36f3136d2ff)) +* **issues:** Add GetEditMeta on issue ([a783764](https://github.com/andygrunwald/go-jira/commit/a783764b52dc890773658ddd0483a9d0393e385d)), closes [/docs.atlassian.com/DAC/rest/jira/6.1.html#d2e1364](https://github.com/andygrunwald//docs.atlassian.com/DAC/rest/jira/6.1.html/issues/d2e1364) +* **IssueService:** allow empty JQL ([#268](https://github.com/andygrunwald/go-jira/issues/268)) ([4b91cf2](https://github.com/andygrunwald/go-jira/commit/4b91cf2b135355de7ecee41727c3e65f4e7067bc)) +* **project:** Add cronjob to check for stale issues ([#287](https://github.com/andygrunwald/go-jira/issues/287)) ([2096b04](https://github.com/andygrunwald/go-jira/commit/2096b04e52b434c1fb1c841bab487a94674a271e)) +* **project:** Add GitHub Actions testing workflow ([#289](https://github.com/andygrunwald/go-jira/issues/289)) ([80c0282](https://github.com/andygrunwald/go-jira/commit/80c02828ca9e4eb0e4a1877275baae14d330a2d9)), closes [#290](https://github.com/andygrunwald/go-jira/issues/290) +* **project:** Add workflow to greet new contributors ([#288](https://github.com/andygrunwald/go-jira/issues/288)) ([c357b61](https://github.com/andygrunwald/go-jira/commit/c357b61a40f62a919ebd94a555390958f99c8db7)) + + +### Bug Fixes + +* change millisecond time format ([8c77107](https://github.com/andygrunwald/go-jira/commit/8c77107df3757c4ec5eae6e9d7c018618e708bfa)) +* paging with load balancer going to endless loop ([19d3fc0](https://github.com/andygrunwald/go-jira/commit/19d3fc0aecde547ffe1ab547c5ffb6c7972d387c)), closes [#260](https://github.com/andygrunwald/go-jira/issues/260) +* **issue:** IssueService.Search() with a not empty JQL triggers 400 bad request ([#292](https://github.com/andygrunwald/go-jira/issues/292)) ([8b64c7f](https://github.com/andygrunwald/go-jira/commit/8b64c7f005fbceb11fa43a7aff3de61eb3166fca)), closes [#291](https://github.com/andygrunwald/go-jira/issues/291) +* **IssueService.GetWatchers:** UserService.GetByAccountID support accountId params ([436469b](https://github.com/andygrunwald/go-jira/commit/436469b62d4d62037f380b38c918a13f4a5f0ab2)) +* **product:** Make product naming consistent, rename JIRA to Jira ([#286](https://github.com/andygrunwald/go-jira/issues/286)) ([146229d](https://github.com/andygrunwald/go-jira/commit/146229d2ab58a3fb128ddc8dcbe03aff72e20857)), closes [#284](https://github.com/andygrunwald/go-jira/issues/284) +* **tests:** Fix TestIssueService_PostAttachment unit test ([f6b1dca](https://github.com/andygrunwald/go-jira/commit/f6b1dcafcfdd8fe69f842b1053c4030da6c97c7f)) +* removing the use of username field in searching for users ([#297](https://github.com/andygrunwald/go-jira/issues/297)) ([f50cb07](https://github.com/andygrunwald/go-jira/commit/f50cb07b297d79138b13e5ab49ea33965d32f5c1)) + +## [1.12.0](https://github.com/andygrunwald/go-jira/compare/v1.11.1...v1.12.0) (2019-12-14) + + +### Features + +* Add IssueLinkTypeService with GetList and test ([261889a](https://github.com/andygrunwald/go-jira/commit/261889adc63623fcea0fa8cab0d5da26eec37e68)) +* add worklog update method ([9ff562a](https://github.com/andygrunwald/go-jira/commit/9ff562ae3ea037961f277be10412ad0a42ff8a6f)) +* Implement get remote links method ([1946cac](https://github.com/andygrunwald/go-jira/commit/1946cac0fe6ee91f784e3dda3c12f3f30f7115b8)) +* Implement issue link type DELETE ([e37cc6c](https://github.com/andygrunwald/go-jira/commit/e37cc6c6897830492c070667ab8b68bd85683fc3)) +* Implement issue link type GET ([57538b9](https://github.com/andygrunwald/go-jira/commit/57538b926c558e97940760a30bdc16cdd37ef4f1)) +* Implement issue link type POST ([75b9df8](https://github.com/andygrunwald/go-jira/commit/75b9df8b01557f01dc318d33c0bc2841a9c084eb)) +* Implement issue link type PUT ([48a15c1](https://github.com/andygrunwald/go-jira/commit/48a15c10443a3cff78f0fb2c8034dd772320e238)) +* provide access to issue transitions loaded from JIRA API ([7530b7c](https://github.com/andygrunwald/go-jira/commit/7530b7cd8266d82cdb4afe831518986772e742ba)) + +### [1.11.1](https://github.com/andygrunwald/go-jira/compare/v1.11.0...v1.11.1) (2019-10-17) + +## [1.11.0](https://github.com/andygrunwald/go-jira/compare/v1.10.0...v1.11.0) (2019-10-17) + + +### Features + +* Add AccountID and AccountType to GroupMember struct ([216e005](https://github.com/andygrunwald/go-jira/commit/216e0056d6385eba9d31cb37e6ff64314860d2cc)) +* Add AccountType and Locale to User struct ([52ab347](https://github.com/andygrunwald/go-jira/commit/52ab34790307144087f0d9bf86c93a2b2209fe46)) +* Add GetAllStatuses ([afc96b1](https://github.com/andygrunwald/go-jira/commit/afc96b18d17b77e32cec9e1ac7e4f5dec7e627f5)) +* Add GetMyFilters to FilterService ([ebae19d](https://github.com/andygrunwald/go-jira/commit/ebae19dda6afd0e54578f30300bc36012381e99b)) +* Add Search to FilterService ([38a755b](https://github.com/andygrunwald/go-jira/commit/38a755b407cd70d11fe2e2897d814552ca29ab51)) +* add support for JWT auth with qsh needed by add-ons ([a8bdfed](https://github.com/andygrunwald/go-jira/commit/a8bdfed27ff42a9bb0468b8cf192871780919def)) +* AddGetBoardConfiguration ([fd698c5](https://github.com/andygrunwald/go-jira/commit/fd698c57163f248f21285d5ebc6a3bb60d46694f)) +* Replace http.Client with interface for extensibility ([b59a65c](https://github.com/andygrunwald/go-jira/commit/b59a65c365dcefd42e135579e9b7ce9c9c006489)) + + +### Bug Fixes + +* Fix fixversion description tag ([8383e2f](https://github.com/andygrunwald/go-jira/commit/8383e2f5f145d04f6bcdb47fb12a95b58bdcedfa)) +* Fix typos in filter_test.go ([e9a261c](https://github.com/andygrunwald/go-jira/commit/e9a261c52249073345e5895b22e2cf4d7286497a)) + +# [1.10.0](https://github.com/andygrunwald/go-jira/compare/v1.9.0...v1.10.0) (2019-05-23) + + +### Bug Fixes + +* empty SearchOptions causing malformed request ([b3bf8c2](https://github.com/andygrunwald/go-jira/commit/b3bf8c2)) + + +### Features + +* added DeleteAttachment ([e93c0e1](https://github.com/andygrunwald/go-jira/commit/e93c0e1)) + + + +# [1.9.0](https://github.com/andygrunwald/go-jira/compare/v1.8.0...v1.9.0) (2019-05-19) + + +### Features + +* **issues:** Added support for AddWorklog and GetWorklogs ([1ebd7e7](https://github.com/andygrunwald/go-jira/commit/1ebd7e7)) + + + +# [1.8.0](https://github.com/andygrunwald/go-jira/compare/v1.7.0...v1.8.0) (2019-05-16) + + +### Bug Fixes + +* Add PriorityService to the main ([8491cb0](https://github.com/andygrunwald/go-jira/commit/8491cb0)) + + +### Features + +* **filter:** Add GetFavouriteList to FilterService. ([645898e](https://github.com/andygrunwald/go-jira/commit/645898e)) +* Add get all priorities ([1c63e25](https://github.com/andygrunwald/go-jira/commit/1c63e25)) +* Add ResolutionService to retrieve resolutions ([fb1ce22](https://github.com/andygrunwald/go-jira/commit/fb1ce22)) +* Add status category constants ([6223ddd](https://github.com/andygrunwald/go-jira/commit/6223ddd)) +* Add StatusCategory GetList ([049a756](https://github.com/andygrunwald/go-jira/commit/049a756)) diff --git a/vendor/github.com/andygrunwald/go-jira/LICENSE b/vendor/github.com/andygrunwald/go-jira/LICENSE new file mode 100644 index 0000000000..692f6bea28 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Andy Grunwald + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/vendor/github.com/andygrunwald/go-jira/Makefile b/vendor/github.com/andygrunwald/go-jira/Makefile new file mode 100644 index 0000000000..928c554c80 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/Makefile @@ -0,0 +1,25 @@ +.DEFAULT_GOAL := help + +.PHONY: help +help: ## Outputs the help. + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: test +test: ## Runs all unit, integration and example tests. + go test -race -v ./... + +.PHONY: vet +vet: ## Runs go vet (to detect suspicious constructs). + go vet ./... + +.PHONY: fmt +fmt: ## Runs go fmt (to check for go coding guidelines). + gofmt -d -s . + +.PHONY: staticcheck +staticcheck: ## Runs static analysis to prevend bugs, foster code simplicity, performance and editor integration. + go get -u honnef.co/go/tools/cmd/staticcheck + staticcheck ./... + +.PHONY: all +all: test vet fmt staticcheck ## Runs all source code quality targets (like test, vet, fmt, staticcheck) diff --git a/vendor/github.com/andygrunwald/go-jira/README.md b/vendor/github.com/andygrunwald/go-jira/README.md new file mode 100644 index 0000000000..571d4c3038 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/README.md @@ -0,0 +1,334 @@ +# go-jira + +[![GoDoc](https://godoc.org/github.com/andygrunwald/go-jira?status.svg)](https://godoc.org/github.com/andygrunwald/go-jira) +[![Build Status](https://github.com/andygrunwald/go-jira/actions/workflows/testing.yml/badge.svg)](https://github.com/andygrunwald/go-jira/actions/workflows/testing.yml) +[![Go Report Card](https://goreportcard.com/badge/github.com/andygrunwald/go-jira)](https://goreportcard.com/report/github.com/andygrunwald/go-jira) + +[Go](https://golang.org/) client library for [Atlassian Jira](https://www.atlassian.com/software/jira). + +![Go client library for Atlassian Jira](./img/logo_small.png "Go client library for Atlassian Jira.") + +## Features + +* Authentication (HTTP Basic, OAuth, Session Cookie) +* Create and retrieve issues +* Create and retrieve issue transitions (status updates) +* Call every API endpoint of the Jira, even if it is not directly implemented in this library + +This package is not Jira API complete (yet), but you can call every API endpoint you want. See [Call a not implemented API endpoint](#call-a-not-implemented-api-endpoint) how to do this. For all possible API endpoints of Jira have a look at [latest Jira REST API documentation](https://docs.atlassian.com/jira/REST/latest/). + +## Requirements + +* Go >= 1.14 +* Jira v6.3.4 & v7.1.2. + +Note that we also run our tests against 1.13, though only the last two versions +of Go are officially supported. + +## Installation + +It is go gettable + +```bash +go get github.com/andygrunwald/go-jira +``` + +For stable versions you can use one of our tags with [gopkg.in](http://labix.org/gopkg.in). E.g. + +```go +package main + +import ( + jira "gopkg.in/andygrunwald/go-jira.v1" +) +... +``` + +(optional) to run unit / example tests: + +```bash +cd $GOPATH/src/github.com/andygrunwald/go-jira +go test -v ./... +``` + +## API + +Please have a look at the [GoDoc documentation](https://godoc.org/github.com/andygrunwald/go-jira) for a detailed API description. + +The [latest Jira REST API documentation](https://docs.atlassian.com/jira/REST/latest/) was the base document for this package. + +## Examples + +Further a few examples how the API can be used. +A few more examples are available in the [GoDoc examples section](https://godoc.org/github.com/andygrunwald/go-jira#pkg-examples). + +### Get a single issue + +Lets retrieve [MESOS-3325](https://issues.apache.org/jira/browse/MESOS-3325) from the [Apache Mesos](http://mesos.apache.org/) project. + +```go +package main + +import ( + "fmt" + jira "github.com/andygrunwald/go-jira" +) + +func main() { + jiraClient, _ := jira.NewClient(nil, "https://issues.apache.org/jira/") + issue, _, _ := jiraClient.Issue.Get("MESOS-3325", nil) + + fmt.Printf("%s: %+v\n", issue.Key, issue.Fields.Summary) + fmt.Printf("Type: %s\n", issue.Fields.Type.Name) + fmt.Printf("Priority: %s\n", issue.Fields.Priority.Name) + + // MESOS-3325: Running mesos-slave@0.23 in a container causes slave to be lost after a restart + // Type: Bug + // Priority: Critical +} +``` + +### Authentication + +The `go-jira` library does not handle most authentication directly. Instead, authentication should be handled within +an `http.Client`. That client can then be passed into the `NewClient` function when creating a jira client. + +For convenience, capability for basic and cookie-based authentication is included in the main library. + +#### Token (Jira on Atlassian Cloud) + +Token-based authentication uses the basic authentication scheme, with a user-generated API token in place of a user's password. You can generate a token for your user [here](https://id.atlassian.com/manage-profile/security/api-tokens). Additional information about Atlassian Cloud API tokens can be found [here](https://confluence.atlassian.com/cloud/api-tokens-938839638.html). + +A more thorough, [runnable example](examples/basicauth/main.go) is provided in the examples directory. + +```go +func main() { + tp := jira.BasicAuthTransport{ + Username: "username", + Password: "token", + } + + client, err := jira.NewClient(tp.Client(), "https://my.jira.com") + + u, _, err := client.User.Get("some_user") + + fmt.Printf("\nEmail: %v\nSuccess!\n", u.EmailAddress) +} +``` + +#### Basic (self-hosted Jira) + +Password-based API authentication works for self-hosted Jira **only**, and has been [deprecated for users of Atlassian Cloud](https://developer.atlassian.com/cloud/jira/platform/deprecation-notice-basic-auth-and-cookie-based-auth/). + +The above token authentication example may be used, substituting a user's password for a generated token. + +#### Authenticate with OAuth + +If you want to connect via OAuth to your Jira Cloud instance checkout the [example of using OAuth authentication with Jira in Go](https://gist.github.com/Lupus/edafe9a7c5c6b13407293d795442fe67) by [@Lupus](https://github.com/Lupus). + +For more details have a look at the [issue #56](https://github.com/andygrunwald/go-jira/issues/56). + +### Create an issue + +Example how to create an issue. + +```go +package main + +import ( + "fmt" + "github.com/andygrunwald/go-jira" +) + +func main() { + base := "https://my.jira.com" + tp := jira.BasicAuthTransport{ + Username: "username", + Password: "token", + } + + jiraClient, err := jira.NewClient(tp.Client(), base) + if err != nil { + panic(err) + } + + i := jira.Issue{ + Fields: &jira.IssueFields{ + Assignee: &jira.User{ + Name: "myuser", + }, + Reporter: &jira.User{ + Name: "youruser", + }, + Description: "Test Issue", + Type: jira.IssueType{ + Name: "Bug", + }, + Project: jira.Project{ + Key: "PROJ1", + }, + Summary: "Just a demo issue", + }, + } + issue, _, err := jiraClient.Issue.Create(&i) + if err != nil { + panic(err) + } + + fmt.Printf("%s: %+v\n", issue.Key, issue.Fields.Summary) +} +``` + +### Change an issue status + +This is how one can change an issue status. In this example, we change the issue from "To Do" to "In Progress." + +```go +package main + +import ( + "fmt" + "github.com/andygrunwald/go-jira" +) + +func main() { + base := "https://my.jira.com" + tp := jira.BasicAuthTransport{ + Username: "username", + Password: "token", + } + + jiraClient, err := jira.NewClient(tp.Client(), base) + if err != nil { + panic(err) + } + + issue, _, _ := jiraClient.Issue.Get("FART-1", nil) + currentStatus := issue.Fields.Status.Name + fmt.Printf("Current status: %s\n", currentStatus) + + var transitionID string + possibleTransitions, _, _ := jiraClient.Issue.GetTransitions("FART-1") + for _, v := range possibleTransitions { + if v.Name == "In Progress" { + transitionID = v.ID + break + } + } + + jiraClient.Issue.DoTransition("FART-1", transitionID) + issue, _, _ = jiraClient.Issue.Get(testIssueID, nil) + fmt.Printf("Status after transition: %+v\n", issue.Fields.Status.Name) +} +``` +### Get all the issues for JQL with Pagination +Jira API has limit on maxResults it can return. You may have a usecase where you need to get all issues for given JQL. +This example shows reference implementation of GetAllIssues function which does pagination on Jira API to get all the issues for given JQL + +please look at [Pagination Example](https://github.com/andygrunwald/go-jira/blob/master/examples/pagination/main.go) + + + + +### Call a not implemented API endpoint + +Not all API endpoints of the Jira API are implemented into *go-jira*. +But you can call them anyway: +Lets get all public projects of [Atlassian`s Jira instance](https://jira.atlassian.com/). + +```go +package main + +import ( + "fmt" + "github.com/andygrunwald/go-jira" +) + +func main() { + base := "https://my.jira.com" + tp := jira.BasicAuthTransport{ + Username: "username", + Password: "token", + } + + jiraClient, err := jira.NewClient(tp.Client(), base) + req, _ := jiraClient.NewRequest("GET", "rest/api/2/project", nil) + + projects := new([]jira.Project) + _, err = jiraClient.Do(req, projects) + if err != nil { + panic(err) + } + + for _, project := range *projects { + fmt.Printf("%s: %s\n", project.Key, project.Name) + } + + // ... + // BAM: Bamboo + // BAMJ: Bamboo Jira Plugin + // CLOV: Clover + // CONF: Confluence + // ... +} +``` + +## Implementations + +* [andygrunwald/jitic](https://github.com/andygrunwald/jitic) - The Jira Ticket Checker + +## Code structure + +The code structure of this package was inspired by [google/go-github](https://github.com/google/go-github). + +There is one main part (the client). +Based on this main client the other endpoints, like Issues or Authentication are extracted in services. E.g. `IssueService` or `AuthenticationService`. +These services own a responsibility of the single endpoints / usecases of Jira. + +## Contribution + +We ❤️ PR's + +Contribution, in any kind of way, is highly welcome! +It doesn't matter if you are not able to write code. +Creating issues or holding talks and help other people to use [go-jira](https://github.com/andygrunwald/go-jira) is contribution, too! +A few examples: + +* Correct typos in the README / documentation +* Reporting bugs +* Implement a new feature or endpoint +* Sharing the love of [go-jira](https://github.com/andygrunwald/go-jira) and help people to get use to it + +If you are new to pull requests, checkout [Collaborating on projects using issues and pull requests / Creating a pull request](https://help.github.com/articles/creating-a-pull-request/). + +### Dependency management + +`go-jira` uses `go modules` for dependency management. After cloning the repo, it's easy to make sure you have the correct dependencies by running `go mod tidy`. + +For adding new dependencies, updating dependencies, and other operations, the [Daily workflow](https://github.com/golang/go/wiki/Modules#daily-workflow) is a good place to start. + +### Sandbox environment for testing + +Jira offers sandbox test environments at http://go.atlassian.com/cloud-dev. + +You can read more about them at https://developer.atlassian.com/blog/2016/04/cloud-ecosystem-dev-env/. + +## Releasing + +Install [standard-version](https://github.com/conventional-changelog/standard-version) +```bash +npm i -g standard-version +``` + +```bash +standard-version +git push --tags +``` + +Manually copy/paste text from changelog (for this new version) into the release on Github.com. E.g. + +[https://github.com/andygrunwald/go-jira/releases/edit/v1.11.0](https://github.com/andygrunwald/go-jira/releases/edit/v1.11.0) + +## License + +This project is released under the terms of the [MIT license](http://en.wikipedia.org/wiki/MIT_License). diff --git a/vendor/github.com/andygrunwald/go-jira/authentication.go b/vendor/github.com/andygrunwald/go-jira/authentication.go new file mode 100644 index 0000000000..fcaf8e10a1 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/authentication.go @@ -0,0 +1,208 @@ +package jira + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" +) + +const ( + // HTTP Basic Authentication + authTypeBasic = 1 + // HTTP Session Authentication + authTypeSession = 2 +) + +// AuthenticationService handles authentication for the Jira instance / API. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#authentication +type AuthenticationService struct { + client *Client + + // Authentication type + authType int + + // Basic auth username + username string + + // Basic auth password + password string +} + +// Session represents a Session JSON response by the Jira API. +type Session struct { + Self string `json:"self,omitempty"` + Name string `json:"name,omitempty"` + Session struct { + Name string `json:"name"` + Value string `json:"value"` + } `json:"session,omitempty"` + LoginInfo struct { + FailedLoginCount int `json:"failedLoginCount"` + LoginCount int `json:"loginCount"` + LastFailedLoginTime string `json:"lastFailedLoginTime"` + PreviousLoginTime string `json:"previousLoginTime"` + } `json:"loginInfo"` + Cookies []*http.Cookie +} + +// AcquireSessionCookieWithContext creates a new session for a user in Jira. +// Once a session has been successfully created it can be used to access any of Jira's remote APIs and also the web UI by passing the appropriate HTTP Cookie header. +// The header will by automatically applied to every API request. +// Note that it is generally preferrable to use HTTP BASIC authentication with the REST API. +// However, this resource may be used to mimic the behaviour of Jira's log-in page (e.g. to display log-in errors to a user). +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session +// +// Deprecated: Use CookieAuthTransport instead +func (s *AuthenticationService) AcquireSessionCookieWithContext(ctx context.Context, username, password string) (bool, error) { + apiEndpoint := "rest/auth/1/session" + body := struct { + Username string `json:"username"` + Password string `json:"password"` + }{ + username, + password, + } + + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, body) + if err != nil { + return false, err + } + + session := new(Session) + resp, err := s.client.Do(req, session) + + if resp != nil { + session.Cookies = resp.Cookies() + } + + if err != nil { + return false, fmt.Errorf("auth at Jira instance failed (HTTP(S) request). %s", err) + } + if resp != nil && resp.StatusCode != 200 { + return false, fmt.Errorf("auth at Jira instance failed (HTTP(S) request). Status code: %d", resp.StatusCode) + } + + s.client.session = session + s.authType = authTypeSession + + return true, nil +} + +// AcquireSessionCookie wraps AcquireSessionCookieWithContext using the background context. +// +// Deprecated: Use CookieAuthTransport instead +func (s *AuthenticationService) AcquireSessionCookie(username, password string) (bool, error) { + return s.AcquireSessionCookieWithContext(context.Background(), username, password) +} + +// SetBasicAuth sets username and password for the basic auth against the Jira instance. +// +// Deprecated: Use BasicAuthTransport instead +func (s *AuthenticationService) SetBasicAuth(username, password string) { + s.username = username + s.password = password + s.authType = authTypeBasic +} + +// Authenticated reports if the current Client has authentication details for Jira +func (s *AuthenticationService) Authenticated() bool { + if s != nil { + if s.authType == authTypeSession { + return s.client.session != nil + } else if s.authType == authTypeBasic { + return s.username != "" + } + + } + return false +} + +// LogoutWithContext logs out the current user that has been authenticated and the session in the client is destroyed. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session +// +// Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the +// client anymore +func (s *AuthenticationService) LogoutWithContext(ctx context.Context) error { + if s.authType != authTypeSession || s.client.session == nil { + return fmt.Errorf("no user is authenticated") + } + + apiEndpoint := "rest/auth/1/session" + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) + if err != nil { + return fmt.Errorf("creating the request to log the user out failed : %s", err) + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return fmt.Errorf("error sending the logout request: %s", err) + } + defer resp.Body.Close() + if resp.StatusCode != 204 { + return fmt.Errorf("the logout was unsuccessful with status %d", resp.StatusCode) + } + + // If logout successful, delete session + s.client.session = nil + + return nil + +} + +// Logout wraps LogoutWithContext using the background context. +// +// Deprecated: Use CookieAuthTransport to create base client. Logging out is as simple as not using the +// client anymore +func (s *AuthenticationService) Logout() error { + return s.LogoutWithContext(context.Background()) +} + +// GetCurrentUserWithContext gets the details of the current user. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session +func (s *AuthenticationService) GetCurrentUserWithContext(ctx context.Context) (*Session, error) { + if s == nil { + return nil, fmt.Errorf("authentication Service is not instantiated") + } + if s.authType != authTypeSession || s.client.session == nil { + return nil, fmt.Errorf("no user is authenticated yet") + } + + apiEndpoint := "rest/auth/1/session" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, fmt.Errorf("could not create request for getting user info : %s", err) + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return nil, fmt.Errorf("error sending request to get user info : %s", err) + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + return nil, fmt.Errorf("getting user info failed with status : %d", resp.StatusCode) + } + ret := new(Session) + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("couldn't read body from the response : %s", err) + } + + err = json.Unmarshal(data, &ret) + + if err != nil { + return nil, fmt.Errorf("could not unmarshall received user info : %s", err) + } + + return ret, nil +} + +// GetCurrentUser wraps GetCurrentUserWithContext using the background context. +func (s *AuthenticationService) GetCurrentUser() (*Session, error) { + return s.GetCurrentUserWithContext(context.Background()) +} diff --git a/vendor/github.com/andygrunwald/go-jira/board.go b/vendor/github.com/andygrunwald/go-jira/board.go new file mode 100644 index 0000000000..890d6e0a01 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/board.go @@ -0,0 +1,315 @@ +package jira + +import ( + "context" + "fmt" + "strconv" + "time" +) + +// BoardService handles Agile Boards for the Jira instance / API. +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/server/ +type BoardService struct { + client *Client +} + +// BoardsList reflects a list of agile boards +type BoardsList struct { + MaxResults int `json:"maxResults" structs:"maxResults"` + StartAt int `json:"startAt" structs:"startAt"` + Total int `json:"total" structs:"total"` + IsLast bool `json:"isLast" structs:"isLast"` + Values []Board `json:"values" structs:"values"` +} + +// Board represents a Jira agile board +type Board struct { + ID int `json:"id,omitempty" structs:"id,omitempty"` + Self string `json:"self,omitempty" structs:"self,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitemtpy"` + Type string `json:"type,omitempty" structs:"type,omitempty"` + FilterID int `json:"filterId,omitempty" structs:"filterId,omitempty"` +} + +// BoardListOptions specifies the optional parameters to the BoardService.GetList +type BoardListOptions struct { + // BoardType filters results to boards of the specified type. + // Valid values: scrum, kanban. + BoardType string `url:"type,omitempty"` + // Name filters results to boards that match or partially match the specified name. + Name string `url:"name,omitempty"` + // ProjectKeyOrID filters results to boards that are relevant to a project. + // Relevance meaning that the JQL filter defined in board contains a reference to a project. + ProjectKeyOrID string `url:"projectKeyOrId,omitempty"` + + SearchOptions +} + +// GetAllSprintsOptions specifies the optional parameters to the BoardService.GetList +type GetAllSprintsOptions struct { + // State filters results to sprints in the specified states, comma-separate list + State string `url:"state,omitempty"` + + SearchOptions +} + +// SprintsList reflects a list of agile sprints +type SprintsList struct { + MaxResults int `json:"maxResults" structs:"maxResults"` + StartAt int `json:"startAt" structs:"startAt"` + Total int `json:"total" structs:"total"` + IsLast bool `json:"isLast" structs:"isLast"` + Values []Sprint `json:"values" structs:"values"` +} + +// Sprint represents a sprint on Jira agile board +type Sprint struct { + ID int `json:"id" structs:"id"` + Name string `json:"name" structs:"name"` + CompleteDate *time.Time `json:"completeDate" structs:"completeDate"` + EndDate *time.Time `json:"endDate" structs:"endDate"` + StartDate *time.Time `json:"startDate" structs:"startDate"` + OriginBoardID int `json:"originBoardId" structs:"originBoardId"` + Self string `json:"self" structs:"self"` + State string `json:"state" structs:"state"` +} + +// BoardConfiguration represents a boardConfiguration of a jira board +type BoardConfiguration struct { + ID int `json:"id"` + Name string `json:"name"` + Self string `json:"self"` + Location BoardConfigurationLocation `json:"location"` + Filter BoardConfigurationFilter `json:"filter"` + SubQuery BoardConfigurationSubQuery `json:"subQuery"` + ColumnConfig BoardConfigurationColumnConfig `json:"columnConfig"` +} + +// BoardConfigurationFilter reference to the filter used by the given board. +type BoardConfigurationFilter struct { + ID string `json:"id"` + Self string `json:"self"` +} + +// BoardConfigurationSubQuery (Kanban only) - JQL subquery used by the given board. +type BoardConfigurationSubQuery struct { + Query string `json:"query"` +} + +// BoardConfigurationLocation reference to the container that the board is located in +type BoardConfigurationLocation struct { + Type string `json:"type"` + Key string `json:"key"` + ID string `json:"id"` + Self string `json:"self"` + Name string `json:"name"` +} + +// BoardConfigurationColumnConfig lists the columns for a given board in the order defined in the column configuration +// with constrainttype (none, issueCount, issueCountExclSubs) +type BoardConfigurationColumnConfig struct { + Columns []BoardConfigurationColumn `json:"columns"` + ConstraintType string `json:"constraintType"` +} + +// BoardConfigurationColumn lists the name of the board with the statuses that maps to a particular column +type BoardConfigurationColumn struct { + Name string `json:"name"` + Status []BoardConfigurationColumnStatus `json:"statuses"` + Min int `json:"min,omitempty"` + Max int `json:"max,omitempty"` +} + +// BoardConfigurationColumnStatus represents a status in the column configuration +type BoardConfigurationColumnStatus struct { + ID string `json:"id"` + Self string `json:"self"` +} + +// GetAllBoardsWithContext will returns all boards. This only includes boards that the user has permission to view. +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getAllBoards +func (s *BoardService) GetAllBoardsWithContext(ctx context.Context, opt *BoardListOptions) (*BoardsList, *Response, error) { + apiEndpoint := "rest/agile/1.0/board" + url, err := addOptions(apiEndpoint, opt) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, nil, err + } + + boards := new(BoardsList) + resp, err := s.client.Do(req, boards) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return boards, resp, err +} + +// GetAllBoards wraps GetAllBoardsWithContext using the background context. +func (s *BoardService) GetAllBoards(opt *BoardListOptions) (*BoardsList, *Response, error) { + return s.GetAllBoardsWithContext(context.Background(), opt) +} + +// GetBoardWithContext will returns the board for the given boardID. +// This board will only be returned if the user has permission to view it. +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-getBoard +func (s *BoardService) GetBoardWithContext(ctx context.Context, boardID int) (*Board, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + board := new(Board) + resp, err := s.client.Do(req, board) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return board, resp, nil +} + +// GetBoard wraps GetBoardWithContext using the background context. +func (s *BoardService) GetBoard(boardID int) (*Board, *Response, error) { + return s.GetBoardWithContext(context.Background(), boardID) +} + +// CreateBoardWithContext creates a new board. Board name, type and filter Id is required. +// name - Must be less than 255 characters. +// type - Valid values: scrum, kanban +// filterId - Id of a filter that the user has permissions to view. +// Note, if the user does not have the 'Create shared objects' permission and tries to create a shared board, a private +// board will be created instead (remember that board sharing depends on the filter sharing). +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-createBoard +func (s *BoardService) CreateBoardWithContext(ctx context.Context, board *Board) (*Board, *Response, error) { + apiEndpoint := "rest/agile/1.0/board" + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, board) + if err != nil { + return nil, nil, err + } + + responseBoard := new(Board) + resp, err := s.client.Do(req, responseBoard) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return responseBoard, resp, nil +} + +// CreateBoard wraps CreateBoardWithContext using the background context. +func (s *BoardService) CreateBoard(board *Board) (*Board, *Response, error) { + return s.CreateBoardWithContext(context.Background(), board) +} + +// DeleteBoardWithContext will delete an agile board. +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board-deleteBoard +// Caller must close resp.Body +func (s *BoardService) DeleteBoardWithContext(ctx context.Context, boardID int) (*Board, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%v", boardID) + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + err = NewJiraError(resp, err) + } + return nil, resp, err +} + +// DeleteBoard wraps DeleteBoardWithContext using the background context. +// Caller must close resp.Body +func (s *BoardService) DeleteBoard(boardID int) (*Board, *Response, error) { + return s.DeleteBoardWithContext(context.Background(), boardID) +} + +// GetAllSprintsWithContext will return all sprints from a board, for a given board Id. +// This only includes sprints that the user has permission to view. +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint +func (s *BoardService) GetAllSprintsWithContext(ctx context.Context, boardID string) ([]Sprint, *Response, error) { + id, err := strconv.Atoi(boardID) + if err != nil { + return nil, nil, err + } + + result, response, err := s.GetAllSprintsWithOptions(id, &GetAllSprintsOptions{}) + if err != nil { + return nil, nil, err + } + + return result.Values, response, nil +} + +// GetAllSprints wraps GetAllSprintsWithContext using the background context. +func (s *BoardService) GetAllSprints(boardID string) ([]Sprint, *Response, error) { + return s.GetAllSprintsWithContext(context.Background(), boardID) +} + +// GetAllSprintsWithOptionsWithContext will return sprints from a board, for a given board Id and filtering options +// This only includes sprints that the user has permission to view. +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/board/{boardId}/sprint +func (s *BoardService) GetAllSprintsWithOptionsWithContext(ctx context.Context, boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/sprint", boardID) + url, err := addOptions(apiEndpoint, options) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, nil, err + } + + result := new(SprintsList) + resp, err := s.client.Do(req, result) + if err != nil { + err = NewJiraError(resp, err) + } + + return result, resp, err +} + +// GetAllSprintsWithOptions wraps GetAllSprintsWithOptionsWithContext using the background context. +func (s *BoardService) GetAllSprintsWithOptions(boardID int, options *GetAllSprintsOptions) (*SprintsList, *Response, error) { + return s.GetAllSprintsWithOptionsWithContext(context.Background(), boardID, options) +} + +// GetBoardConfigurationWithContext will return a board configuration for a given board Id +// Jira API docs:https://developer.atlassian.com/cloud/jira/software/rest/#api-rest-agile-1-0-board-boardId-configuration-get +func (s *BoardService) GetBoardConfigurationWithContext(ctx context.Context, boardID int) (*BoardConfiguration, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/agile/1.0/board/%d/configuration", boardID) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + + if err != nil { + return nil, nil, err + } + + result := new(BoardConfiguration) + resp, err := s.client.Do(req, result) + if err != nil { + err = NewJiraError(resp, err) + } + + return result, resp, err + +} + +// GetBoardConfiguration wraps GetBoardConfigurationWithContext using the background context. +func (s *BoardService) GetBoardConfiguration(boardID int) (*BoardConfiguration, *Response, error) { + return s.GetBoardConfigurationWithContext(context.Background(), boardID) +} diff --git a/vendor/github.com/andygrunwald/go-jira/component.go b/vendor/github.com/andygrunwald/go-jira/component.go new file mode 100644 index 0000000000..b76fe0cf01 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/component.go @@ -0,0 +1,44 @@ +package jira + +import "context" + +// ComponentService handles components for the Jira instance / API.// +// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.1/#api/2/component +type ComponentService struct { + client *Client +} + +// CreateComponentOptions are passed to the ComponentService.Create function to create a new Jira component +type CreateComponentOptions struct { + Name string `json:"name,omitempty" structs:"name,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` + Lead *User `json:"lead,omitempty" structs:"lead,omitempty"` + LeadUserName string `json:"leadUserName,omitempty" structs:"leadUserName,omitempty"` + AssigneeType string `json:"assigneeType,omitempty" structs:"assigneeType,omitempty"` + Assignee *User `json:"assignee,omitempty" structs:"assignee,omitempty"` + Project string `json:"project,omitempty" structs:"project,omitempty"` + ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"` +} + +// CreateWithContext creates a new Jira component based on the given options. +func (s *ComponentService) CreateWithContext(ctx context.Context, options *CreateComponentOptions) (*ProjectComponent, *Response, error) { + apiEndpoint := "rest/api/2/component" + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, options) + if err != nil { + return nil, nil, err + } + + component := new(ProjectComponent) + resp, err := s.client.Do(req, component) + + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + + return component, resp, nil +} + +// Create wraps CreateWithContext using the background context. +func (s *ComponentService) Create(options *CreateComponentOptions) (*ProjectComponent, *Response, error) { + return s.CreateWithContext(context.Background(), options) +} diff --git a/vendor/github.com/andygrunwald/go-jira/customer.go b/vendor/github.com/andygrunwald/go-jira/customer.go new file mode 100644 index 0000000000..3df31c1c4b --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/customer.go @@ -0,0 +1,72 @@ +package jira + +import ( + "context" + "net/http" +) + +// CustomerService handles ServiceDesk customers for the Jira instance / API. +type CustomerService struct { + client *Client +} + +// Customer represents a ServiceDesk customer. +type Customer struct { + AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Key string `json:"key,omitempty" structs:"key,omitempty"` + EmailAddress string `json:"emailAddress,omitempty" structs:"emailAddress,omitempty"` + DisplayName string `json:"displayName,omitempty" structs:"displayName,omitempty"` + Active *bool `json:"active,omitempty" structs:"active,omitempty"` + TimeZone string `json:"timeZone,omitempty" structs:"timeZone,omitempty"` + Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"` +} + +// CustomerListOptions is the query options for listing customers. +type CustomerListOptions struct { + Query string `url:"query,omitempty"` + Start int `url:"start,omitempty"` + Limit int `url:"limit,omitempty"` +} + +// CustomerList is a page of customers. +type CustomerList struct { + Values []Customer `json:"values,omitempty" structs:"values,omitempty"` + Start int `json:"start,omitempty" structs:"start,omitempty"` + Limit int `json:"limit,omitempty" structs:"limit,omitempty"` + IsLast bool `json:"isLastPage,omitempty" structs:"isLastPage,omitempty"` + Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"` +} + +// CreateWithContext creates a ServiceDesk customer. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-customer/#api-rest-servicedeskapi-customer-post +func (c *CustomerService) CreateWithContext(ctx context.Context, email, displayName string) (*Customer, *Response, error) { + const apiEndpoint = "rest/servicedeskapi/customer" + + payload := struct { + Email string `json:"email"` + DisplayName string `json:"displayName"` + }{ + Email: email, + DisplayName: displayName, + } + + req, err := c.client.NewRequestWithContext(ctx, http.MethodPost, apiEndpoint, payload) + if err != nil { + return nil, nil, err + } + + responseCustomer := new(Customer) + resp, err := c.client.Do(req, responseCustomer) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + + return responseCustomer, resp, nil +} + +// Create wraps CreateWithContext using the background context. +func (c *CustomerService) Create(email, displayName string) (*Customer, *Response, error) { + return c.CreateWithContext(context.Background(), email, displayName) +} diff --git a/vendor/github.com/andygrunwald/go-jira/error.go b/vendor/github.com/andygrunwald/go-jira/error.go new file mode 100644 index 0000000000..c7bc2e58e5 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/error.go @@ -0,0 +1,90 @@ +package jira + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "strings" + + "github.com/pkg/errors" +) + +// Error message from Jira +// See https://docs.atlassian.com/jira/REST/cloud/#error-responses +type Error struct { + HTTPError error + ErrorMessages []string `json:"errorMessages"` + Errors map[string]string `json:"errors"` +} + +// NewJiraError creates a new jira Error +func NewJiraError(resp *Response, httpError error) error { + if resp == nil { + return errors.Wrap(httpError, "No response returned") + } + + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return errors.Wrap(err, httpError.Error()) + } + jerr := Error{HTTPError: httpError} + contentType := resp.Header.Get("Content-Type") + if strings.HasPrefix(contentType, "application/json") { + err = json.Unmarshal(body, &jerr) + if err != nil { + httpError = errors.Wrap(errors.New("could not parse JSON"), httpError.Error()) + return errors.Wrap(err, httpError.Error()) + } + } else { + if httpError == nil { + return fmt.Errorf("got response status %s:%s", resp.Status, string(body)) + } + return errors.Wrap(httpError, fmt.Sprintf("%s: %s", resp.Status, string(body))) + } + + return &jerr +} + +// Error is a short string representing the error +func (e *Error) Error() string { + if len(e.ErrorMessages) > 0 { + // return fmt.Sprintf("%v", e.HTTPError) + return fmt.Sprintf("%s: %v", e.ErrorMessages[0], e.HTTPError) + } + if len(e.Errors) > 0 { + for key, value := range e.Errors { + return fmt.Sprintf("%s - %s: %v", key, value, e.HTTPError) + } + } + return e.HTTPError.Error() +} + +// LongError is a full representation of the error as a string +func (e *Error) LongError() string { + var msg bytes.Buffer + if e.HTTPError != nil { + msg.WriteString("Original:\n") + msg.WriteString(e.HTTPError.Error()) + msg.WriteString("\n") + } + if len(e.ErrorMessages) > 0 { + msg.WriteString("Messages:\n") + for _, v := range e.ErrorMessages { + msg.WriteString(" - ") + msg.WriteString(v) + msg.WriteString("\n") + } + } + if len(e.Errors) > 0 { + for key, value := range e.Errors { + msg.WriteString(" - ") + msg.WriteString(key) + msg.WriteString(" - ") + msg.WriteString(value) + msg.WriteString("\n") + } + } + return msg.String() +} diff --git a/vendor/github.com/andygrunwald/go-jira/field.go b/vendor/github.com/andygrunwald/go-jira/field.go new file mode 100644 index 0000000000..b14057d932 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/field.go @@ -0,0 +1,55 @@ +package jira + +import "context" + +// FieldService handles fields for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Field +type FieldService struct { + client *Client +} + +// Field represents a field of a Jira issue. +type Field struct { + ID string `json:"id,omitempty" structs:"id,omitempty"` + Key string `json:"key,omitempty" structs:"key,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Custom bool `json:"custom,omitempty" structs:"custom,omitempty"` + Navigable bool `json:"navigable,omitempty" structs:"navigable,omitempty"` + Searchable bool `json:"searchable,omitempty" structs:"searchable,omitempty"` + ClauseNames []string `json:"clauseNames,omitempty" structs:"clauseNames,omitempty"` + Schema FieldSchema `json:"schema,omitempty" structs:"schema,omitempty"` +} + +// FieldSchema represents a schema of a Jira field. +// Documentation: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-fields/#api-rest-api-2-field-get +type FieldSchema struct { + Type string `json:"type,omitempty" structs:"type,omitempty"` + Items string `json:"items,omitempty" structs:"items,omitempty"` + Custom string `json:"custom,omitempty" structs:"custom,omitempty"` + System string `json:"system,omitempty" structs:"system,omitempty"` + CustomID int64 `json:"customId,omitempty" structs:"customId,omitempty"` +} + +// GetListWithContext gets all fields from Jira +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-field-get +func (s *FieldService) GetListWithContext(ctx context.Context) ([]Field, *Response, error) { + apiEndpoint := "rest/api/2/field" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + fieldList := []Field{} + resp, err := s.client.Do(req, &fieldList) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return fieldList, resp, nil +} + +// GetList wraps GetListWithContext using the background context. +func (s *FieldService) GetList() ([]Field, *Response, error) { + return s.GetListWithContext(context.Background()) +} diff --git a/vendor/github.com/andygrunwald/go-jira/filter.go b/vendor/github.com/andygrunwald/go-jira/filter.go new file mode 100644 index 0000000000..f40f3a58c8 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/filter.go @@ -0,0 +1,251 @@ +package jira + +import ( + "context" + "fmt" + + "github.com/google/go-querystring/query" +) + +// FilterService handles fields for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Filter +type FilterService struct { + client *Client +} + +// Filter represents a Filter in Jira +type Filter struct { + Self string `json:"self"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Owner User `json:"owner"` + Jql string `json:"jql"` + ViewURL string `json:"viewUrl"` + SearchURL string `json:"searchUrl"` + Favourite bool `json:"favourite"` + FavouritedCount int `json:"favouritedCount"` + SharePermissions []interface{} `json:"sharePermissions"` + Subscriptions struct { + Size int `json:"size"` + Items []interface{} `json:"items"` + MaxResults int `json:"max-results"` + StartIndex int `json:"start-index"` + EndIndex int `json:"end-index"` + } `json:"subscriptions"` +} + +// GetMyFiltersQueryOptions specifies the optional parameters for the Get My Filters method +type GetMyFiltersQueryOptions struct { + IncludeFavourites bool `url:"includeFavourites,omitempty"` + Expand string `url:"expand,omitempty"` +} + +// FiltersList reflects a list of filters +type FiltersList struct { + MaxResults int `json:"maxResults" structs:"maxResults"` + StartAt int `json:"startAt" structs:"startAt"` + Total int `json:"total" structs:"total"` + IsLast bool `json:"isLast" structs:"isLast"` + Values []FiltersListItem `json:"values" structs:"values"` +} + +// FiltersListItem represents a Filter of FiltersList in Jira +type FiltersListItem struct { + Self string `json:"self"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Owner User `json:"owner"` + Jql string `json:"jql"` + ViewURL string `json:"viewUrl"` + SearchURL string `json:"searchUrl"` + Favourite bool `json:"favourite"` + FavouritedCount int `json:"favouritedCount"` + SharePermissions []interface{} `json:"sharePermissions"` + Subscriptions []struct { + ID int `json:"id"` + User User `json:"user"` + } `json:"subscriptions"` +} + +// FilterSearchOptions specifies the optional parameters for the Search method +// https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-search-get +type FilterSearchOptions struct { + // String used to perform a case-insensitive partial match with name. + FilterName string `url:"filterName,omitempty"` + + // User account ID used to return filters with the matching owner.accountId. This parameter cannot be used with owner. + AccountID string `url:"accountId,omitempty"` + + // Group name used to returns filters that are shared with a group that matches sharePermissions.group.groupname. + GroupName string `url:"groupname,omitempty"` + + // Project ID used to returns filters that are shared with a project that matches sharePermissions.project.id. + // Format: int64 + ProjectID int64 `url:"projectId,omitempty"` + + // Orders the results using one of these filter properties. + // - `description` Orders by filter `description`. Note that this ordering works independently of whether the expand to display the description field is in use. + // - `favourite_count` Orders by `favouritedCount`. + // - `is_favourite` Orders by `favourite`. + // - `id` Orders by filter `id`. + // - `name` Orders by filter `name`. + // - `owner` Orders by `owner.accountId`. + // + // Default: `name` + // + // Valid values: id, name, description, owner, favorite_count, is_favorite, -id, -name, -description, -owner, -favorite_count, -is_favorite + OrderBy string `url:"orderBy,omitempty"` + + // The index of the first item to return in a page of results (page offset). + // Default: 0, Format: int64 + StartAt int64 `url:"startAt,omitempty"` + + // The maximum number of items to return per page. The maximum is 100. + // Default: 50, Format: int32 + MaxResults int32 `url:"maxResults,omitempty"` + + // Use expand to include additional information about filter in the response. This parameter accepts multiple values separated by a comma: + // - description Returns the description of the filter. + // - favourite Returns an indicator of whether the user has set the filter as a favorite. + // - favouritedCount Returns a count of how many users have set this filter as a favorite. + // - jql Returns the JQL query that the filter uses. + // - owner Returns the owner of the filter. + // - searchUrl Returns a URL to perform the filter's JQL query. + // - sharePermissions Returns the share permissions defined for the filter. + // - subscriptions Returns the users that are subscribed to the filter. + // - viewUrl Returns a URL to view the filter. + Expand string `url:"expand,omitempty"` +} + +// GetListWithContext retrieves all filters from Jira +func (fs *FilterService) GetListWithContext(ctx context.Context) ([]*Filter, *Response, error) { + + options := &GetQueryOptions{} + apiEndpoint := "rest/api/2/filter" + req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + q, err := query.Values(options) + if err != nil { + return nil, nil, err + } + req.URL.RawQuery = q.Encode() + + filters := []*Filter{} + resp, err := fs.client.Do(req, &filters) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + return filters, resp, err +} + +// GetList wraps GetListWithContext using the background context. +func (fs *FilterService) GetList() ([]*Filter, *Response, error) { + return fs.GetListWithContext(context.Background()) +} + +// GetFavouriteListWithContext retrieves the user's favourited filters from Jira +func (fs *FilterService) GetFavouriteListWithContext(ctx context.Context) ([]*Filter, *Response, error) { + apiEndpoint := "rest/api/2/filter/favourite" + req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + filters := []*Filter{} + resp, err := fs.client.Do(req, &filters) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + return filters, resp, err +} + +// GetFavouriteList wraps GetFavouriteListWithContext using the background context. +func (fs *FilterService) GetFavouriteList() ([]*Filter, *Response, error) { + return fs.GetFavouriteListWithContext(context.Background()) +} + +// GetWithContext retrieves a single Filter from Jira +func (fs *FilterService) GetWithContext(ctx context.Context, filterID int) (*Filter, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/filter/%d", filterID) + req, err := fs.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + filter := new(Filter) + resp, err := fs.client.Do(req, filter) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return filter, resp, err +} + +// Get wraps GetWithContext using the background context. +func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) { + return fs.GetWithContext(context.Background(), filterID) +} + +// GetMyFiltersWithContext retrieves the my Filters. +// +// https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-my-get +func (fs *FilterService) GetMyFiltersWithContext(ctx context.Context, opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) { + apiEndpoint := "rest/api/3/filter/my" + url, err := addOptions(apiEndpoint, opts) + if err != nil { + return nil, nil, err + } + req, err := fs.client.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, nil, err + } + + filters := []*Filter{} + resp, err := fs.client.Do(req, &filters) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + return filters, resp, nil +} + +// GetMyFilters wraps GetMyFiltersWithContext using the background context. +func (fs *FilterService) GetMyFilters(opts *GetMyFiltersQueryOptions) ([]*Filter, *Response, error) { + return fs.GetMyFiltersWithContext(context.Background(), opts) +} + +// SearchWithContext will search for filter according to the search options +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-rest-api-3-filter-search-get +func (fs *FilterService) SearchWithContext(ctx context.Context, opt *FilterSearchOptions) (*FiltersList, *Response, error) { + apiEndpoint := "rest/api/3/filter/search" + url, err := addOptions(apiEndpoint, opt) + if err != nil { + return nil, nil, err + } + req, err := fs.client.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, nil, err + } + + filters := new(FiltersList) + resp, err := fs.client.Do(req, filters) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return filters, resp, err +} + +// Search wraps SearchWithContext using the background context. +func (fs *FilterService) Search(opt *FilterSearchOptions) (*FiltersList, *Response, error) { + return fs.SearchWithContext(context.Background(), opt) +} diff --git a/vendor/github.com/andygrunwald/go-jira/group.go b/vendor/github.com/andygrunwald/go-jira/group.go new file mode 100644 index 0000000000..f78c6810e8 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/group.go @@ -0,0 +1,179 @@ +package jira + +import ( + "context" + "fmt" + "net/url" +) + +// GroupService handles Groups for the Jira instance / API. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group +type GroupService struct { + client *Client +} + +// groupMembersResult is only a small wrapper around the Group* methods +// to be able to parse the results +type groupMembersResult struct { + StartAt int `json:"startAt"` + MaxResults int `json:"maxResults"` + Total int `json:"total"` + Members []GroupMember `json:"values"` +} + +// Group represents a Jira group +type Group struct { + ID string `json:"id"` + Title string `json:"title"` + Type string `json:"type"` + Properties groupProperties `json:"properties"` + AdditionalProperties bool `json:"additionalProperties"` +} + +type groupProperties struct { + Name groupPropertiesName `json:"name"` +} + +type groupPropertiesName struct { + Type string `json:"type"` +} + +// GroupMember reflects a single member of a group +type GroupMember struct { + Self string `json:"self,omitempty"` + Name string `json:"name,omitempty"` + Key string `json:"key,omitempty"` + AccountID string `json:"accountId,omitempty"` + EmailAddress string `json:"emailAddress,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Active bool `json:"active,omitempty"` + TimeZone string `json:"timeZone,omitempty"` + AccountType string `json:"accountType,omitempty"` +} + +// GroupSearchOptions specifies the optional parameters for the Get Group methods +type GroupSearchOptions struct { + StartAt int + MaxResults int + IncludeInactiveUsers bool +} + +// GetWithContext returns a paginated list of users who are members of the specified group and its subgroups. +// Users in the page are ordered by user names. +// User of this resource is required to have sysadmin or admin permissions. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup +// +// WARNING: This API only returns the first page of group members +func (s *GroupService) GetWithContext(ctx context.Context, name string) ([]GroupMember, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/group/member?groupname=%s", url.QueryEscape(name)) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + group := new(groupMembersResult) + resp, err := s.client.Do(req, group) + if err != nil { + return nil, resp, err + } + + return group.Members, resp, nil +} + +// Get wraps GetWithContext using the background context. +func (s *GroupService) Get(name string) ([]GroupMember, *Response, error) { + return s.GetWithContext(context.Background(), name) +} + +// GetWithOptionsWithContext returns a paginated list of members of the specified group and its subgroups. +// Users in the page are ordered by user names. +// User of this resource is required to have sysadmin or admin permissions. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/server/#api/2/group-getUsersFromGroup +func (s *GroupService) GetWithOptionsWithContext(ctx context.Context, name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) { + var apiEndpoint string + if options == nil { + apiEndpoint = fmt.Sprintf("/rest/api/2/group/member?groupname=%s", url.QueryEscape(name)) + } else { + apiEndpoint = fmt.Sprintf( + "/rest/api/2/group/member?groupname=%s&startAt=%d&maxResults=%d&includeInactiveUsers=%t", + url.QueryEscape(name), + options.StartAt, + options.MaxResults, + options.IncludeInactiveUsers, + ) + } + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + group := new(groupMembersResult) + resp, err := s.client.Do(req, group) + if err != nil { + return nil, resp, err + } + return group.Members, resp, nil +} + +// GetWithOptions wraps GetWithOptionsWithContext using the background context. +func (s *GroupService) GetWithOptions(name string, options *GroupSearchOptions) ([]GroupMember, *Response, error) { + return s.GetWithOptionsWithContext(context.Background(), name, options) +} + +// AddWithContext adds user to group +// +// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-addUserToGroup +func (s *GroupService) AddWithContext(ctx context.Context, groupname string, username string) (*Group, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s", groupname) + var user struct { + Name string `json:"name"` + } + user.Name = username + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, &user) + if err != nil { + return nil, nil, err + } + + responseGroup := new(Group) + resp, err := s.client.Do(req, responseGroup) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return responseGroup, resp, nil +} + +// Add wraps AddWithContext using the background context. +func (s *GroupService) Add(groupname string, username string) (*Group, *Response, error) { + return s.AddWithContext(context.Background(), groupname, username) +} + +// RemoveWithContext removes user from group +// +// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/group-removeUserFromGroup +// Caller must close resp.Body +func (s *GroupService) RemoveWithContext(ctx context.Context, groupname string, username string) (*Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/group/user?groupname=%s&username=%s", groupname, username) + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// Remove wraps RemoveWithContext using the background context. +// Caller must close resp.Body +func (s *GroupService) Remove(groupname string, username string) (*Response, error) { + return s.RemoveWithContext(context.Background(), groupname, username) +} diff --git a/vendor/github.com/andygrunwald/go-jira/issue.go b/vendor/github.com/andygrunwald/go-jira/issue.go new file mode 100644 index 0000000000..0aa03b700d --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/issue.go @@ -0,0 +1,1597 @@ +package jira + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "mime/multipart" + "net/http" + "net/url" + "reflect" + "strconv" + "strings" + "time" + + "github.com/fatih/structs" + "github.com/google/go-querystring/query" + "github.com/trivago/tgo/tcontainer" +) + +const ( + // AssigneeAutomatic represents the value of the "Assignee: Automatic" of Jira + AssigneeAutomatic = "-1" +) + +// IssueService handles Issues for the Jira instance / API. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue +type IssueService struct { + client *Client +} + +// UpdateQueryOptions specifies the optional parameters to the Edit issue +type UpdateQueryOptions struct { + NotifyUsers bool `url:"notifyUsers,omitempty"` + OverrideScreenSecurity bool `url:"overrideScreenSecurity,omitempty"` + OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"` +} + +// Issue represents a Jira issue. +type Issue struct { + Expand string `json:"expand,omitempty" structs:"expand,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + Self string `json:"self,omitempty" structs:"self,omitempty"` + Key string `json:"key,omitempty" structs:"key,omitempty"` + Fields *IssueFields `json:"fields,omitempty" structs:"fields,omitempty"` + RenderedFields *IssueRenderedFields `json:"renderedFields,omitempty" structs:"renderedFields,omitempty"` + Changelog *Changelog `json:"changelog,omitempty" structs:"changelog,omitempty"` + Transitions []Transition `json:"transitions,omitempty" structs:"transitions,omitempty"` + Names map[string]string `json:"names,omitempty" structs:"names,omitempty"` +} + +// ChangelogItems reflects one single changelog item of a history item +type ChangelogItems struct { + Field string `json:"field" structs:"field"` + FieldType string `json:"fieldtype" structs:"fieldtype"` + From interface{} `json:"from" structs:"from"` + FromString string `json:"fromString" structs:"fromString"` + To interface{} `json:"to" structs:"to"` + ToString string `json:"toString" structs:"toString"` +} + +// ChangelogHistory reflects one single changelog history entry +type ChangelogHistory struct { + Id string `json:"id" structs:"id"` + Author User `json:"author" structs:"author"` + Created string `json:"created" structs:"created"` + Items []ChangelogItems `json:"items" structs:"items"` +} + +// Changelog reflects the change log of an issue +type Changelog struct { + Histories []ChangelogHistory `json:"histories,omitempty"` +} + +// Attachment represents a Jira attachment +type Attachment struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + Filename string `json:"filename,omitempty" structs:"filename,omitempty"` + Author *User `json:"author,omitempty" structs:"author,omitempty"` + Created string `json:"created,omitempty" structs:"created,omitempty"` + Size int `json:"size,omitempty" structs:"size,omitempty"` + MimeType string `json:"mimeType,omitempty" structs:"mimeType,omitempty"` + Content string `json:"content,omitempty" structs:"content,omitempty"` + Thumbnail string `json:"thumbnail,omitempty" structs:"thumbnail,omitempty"` +} + +// Epic represents the epic to which an issue is associated +// Not that this struct does not process the returned "color" value +type Epic struct { + ID int `json:"id" structs:"id"` + Key string `json:"key" structs:"key"` + Self string `json:"self" structs:"self"` + Name string `json:"name" structs:"name"` + Summary string `json:"summary" structs:"summary"` + Done bool `json:"done" structs:"done"` +} + +// IssueFields represents single fields of a Jira issue. +// Every Jira issue has several fields attached. +type IssueFields struct { + // TODO Missing fields + // * "workratio": -1, + // * "lastViewed": null, + // * "environment": null, + Expand string `json:"expand,omitempty" structs:"expand,omitempty"` + Type IssueType `json:"issuetype,omitempty" structs:"issuetype,omitempty"` + Project Project `json:"project,omitempty" structs:"project,omitempty"` + Environment string `json:"environment,omitempty" structs:"environment,omitempty"` + Resolution *Resolution `json:"resolution,omitempty" structs:"resolution,omitempty"` + Priority *Priority `json:"priority,omitempty" structs:"priority,omitempty"` + Resolutiondate Time `json:"resolutiondate,omitempty" structs:"resolutiondate,omitempty"` + Created Time `json:"created,omitempty" structs:"created,omitempty"` + Duedate Date `json:"duedate,omitempty" structs:"duedate,omitempty"` + Watches *Watches `json:"watches,omitempty" structs:"watches,omitempty"` + Assignee *User `json:"assignee,omitempty" structs:"assignee,omitempty"` + Updated Time `json:"updated,omitempty" structs:"updated,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` + Summary string `json:"summary,omitempty" structs:"summary,omitempty"` + Creator *User `json:"Creator,omitempty" structs:"Creator,omitempty"` + Reporter *User `json:"reporter,omitempty" structs:"reporter,omitempty"` + Components []*Component `json:"components,omitempty" structs:"components,omitempty"` + Status *Status `json:"status,omitempty" structs:"status,omitempty"` + Progress *Progress `json:"progress,omitempty" structs:"progress,omitempty"` + AggregateProgress *Progress `json:"aggregateprogress,omitempty" structs:"aggregateprogress,omitempty"` + TimeTracking *TimeTracking `json:"timetracking,omitempty" structs:"timetracking,omitempty"` + TimeSpent int `json:"timespent,omitempty" structs:"timespent,omitempty"` + TimeEstimate int `json:"timeestimate,omitempty" structs:"timeestimate,omitempty"` + TimeOriginalEstimate int `json:"timeoriginalestimate,omitempty" structs:"timeoriginalestimate,omitempty"` + Worklog *Worklog `json:"worklog,omitempty" structs:"worklog,omitempty"` + IssueLinks []*IssueLink `json:"issuelinks,omitempty" structs:"issuelinks,omitempty"` + Comments *Comments `json:"comment,omitempty" structs:"comment,omitempty"` + FixVersions []*FixVersion `json:"fixVersions,omitempty" structs:"fixVersions,omitempty"` + AffectsVersions []*AffectsVersion `json:"versions,omitempty" structs:"versions,omitempty"` + Labels []string `json:"labels,omitempty" structs:"labels,omitempty"` + Subtasks []*Subtasks `json:"subtasks,omitempty" structs:"subtasks,omitempty"` + Attachments []*Attachment `json:"attachment,omitempty" structs:"attachment,omitempty"` + Epic *Epic `json:"epic,omitempty" structs:"epic,omitempty"` + Sprint *Sprint `json:"sprint,omitempty" structs:"sprint,omitempty"` + Parent *Parent `json:"parent,omitempty" structs:"parent,omitempty"` + AggregateTimeOriginalEstimate int `json:"aggregatetimeoriginalestimate,omitempty" structs:"aggregatetimeoriginalestimate,omitempty"` + AggregateTimeSpent int `json:"aggregatetimespent,omitempty" structs:"aggregatetimespent,omitempty"` + AggregateTimeEstimate int `json:"aggregatetimeestimate,omitempty" structs:"aggregatetimeestimate,omitempty"` + Unknowns tcontainer.MarshalMap +} + +// MarshalJSON is a custom JSON marshal function for the IssueFields structs. +// It handles Jira custom fields and maps those from / to "Unknowns" key. +func (i *IssueFields) MarshalJSON() ([]byte, error) { + m := structs.Map(i) + unknowns, okay := m["Unknowns"] + if okay { + // if unknowns present, shift all key value from unknown to a level up + for key, value := range unknowns.(tcontainer.MarshalMap) { + m[key] = value + } + delete(m, "Unknowns") + } + return json.Marshal(m) +} + +// UnmarshalJSON is a custom JSON marshal function for the IssueFields structs. +// It handles Jira custom fields and maps those from / to "Unknowns" key. +func (i *IssueFields) UnmarshalJSON(data []byte) error { + + // Do the normal unmarshalling first + // Details for this way: http://choly.ca/post/go-json-marshalling/ + type Alias IssueFields + aux := &struct { + *Alias + }{ + Alias: (*Alias)(i), + } + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + totalMap := tcontainer.NewMarshalMap() + err := json.Unmarshal(data, &totalMap) + if err != nil { + return err + } + + t := reflect.TypeOf(*i) + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + tagDetail := field.Tag.Get("json") + if tagDetail == "" { + // ignore if there are no tags + continue + } + options := strings.Split(tagDetail, ",") + + if len(options) == 0 { + return fmt.Errorf("no tags options found for %s", field.Name) + } + // the first one is the json tag + key := options[0] + if _, okay := totalMap.Value(key); okay { + delete(totalMap, key) + } + + } + i = (*IssueFields)(aux.Alias) + // all the tags found in the struct were removed. Whatever is left are unknowns to struct + i.Unknowns = totalMap + return nil + +} + +// IssueRenderedFields represents rendered fields of a Jira issue. +// Not all IssueFields are rendered. +type IssueRenderedFields struct { + // TODO Missing fields + // * "aggregatetimespent": null, + // * "workratio": -1, + // * "lastViewed": null, + // * "aggregatetimeoriginalestimate": null, + // * "aggregatetimeestimate": null, + // * "environment": null, + Resolutiondate string `json:"resolutiondate,omitempty" structs:"resolutiondate,omitempty"` + Created string `json:"created,omitempty" structs:"created,omitempty"` + Duedate string `json:"duedate,omitempty" structs:"duedate,omitempty"` + Updated string `json:"updated,omitempty" structs:"updated,omitempty"` + Comments *Comments `json:"comment,omitempty" structs:"comment,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` +} + +// IssueType represents a type of a Jira issue. +// Typical types are "Request", "Bug", "Story", ... +type IssueType struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` + IconURL string `json:"iconUrl,omitempty" structs:"iconUrl,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Subtask bool `json:"subtask,omitempty" structs:"subtask,omitempty"` + AvatarID int `json:"avatarId,omitempty" structs:"avatarId,omitempty"` +} + +// Watches represents a type of how many and which user are "observing" a Jira issue to track the status / updates. +type Watches struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + WatchCount int `json:"watchCount,omitempty" structs:"watchCount,omitempty"` + IsWatching bool `json:"isWatching,omitempty" structs:"isWatching,omitempty"` + Watchers []*Watcher `json:"watchers,omitempty" structs:"watchers,omitempty"` +} + +// Watcher represents a simplified user that "observes" the issue +type Watcher struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"` + DisplayName string `json:"displayName,omitempty" structs:"displayName,omitempty"` + Active bool `json:"active,omitempty" structs:"active,omitempty"` +} + +// AvatarUrls represents different dimensions of avatars / images +type AvatarUrls struct { + Four8X48 string `json:"48x48,omitempty" structs:"48x48,omitempty"` + Two4X24 string `json:"24x24,omitempty" structs:"24x24,omitempty"` + One6X16 string `json:"16x16,omitempty" structs:"16x16,omitempty"` + Three2X32 string `json:"32x32,omitempty" structs:"32x32,omitempty"` +} + +// Component represents a "component" of a Jira issue. +// Components can be user defined in every Jira instance. +type Component struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` +} + +// Progress represents the progress of a Jira issue. +type Progress struct { + Progress int `json:"progress" structs:"progress"` + Total int `json:"total" structs:"total"` + Percent int `json:"percent" structs:"percent"` +} + +// Parent represents the parent of a Jira issue, to be used with subtask issue types. +type Parent struct { + ID string `json:"id,omitempty" structs:"id,omitempty"` + Key string `json:"key,omitempty" structs:"key,omitempty"` +} + +// Time represents the Time definition of Jira as a time.Time of go +type Time time.Time + +func (t Time) Equal(u Time) bool { + return time.Time(t).Equal(time.Time(u)) +} + +// Date represents the Date definition of Jira as a time.Time of go +type Date time.Time + +// Wrapper struct for search result +type transitionResult struct { + Transitions []Transition `json:"transitions" structs:"transitions"` +} + +// Transition represents an issue transition in Jira +type Transition struct { + ID string `json:"id" structs:"id"` + Name string `json:"name" structs:"name"` + To Status `json:"to" structs:"status"` + Fields map[string]TransitionField `json:"fields" structs:"fields"` +} + +// TransitionField represents the value of one Transition +type TransitionField struct { + Required bool `json:"required" structs:"required"` +} + +// CreateTransitionPayload is used for creating new issue transitions +type CreateTransitionPayload struct { + Update TransitionPayloadUpdate `json:"update,omitempty" structs:"update,omitempty"` + Transition TransitionPayload `json:"transition" structs:"transition"` + Fields TransitionPayloadFields `json:"fields" structs:"fields"` +} + +// TransitionPayloadUpdate represents the updates of Transition calls like DoTransition +type TransitionPayloadUpdate struct { + Comment []TransitionPayloadComment `json:"comment,omitempty" structs:"comment,omitempty"` +} + +// TransitionPayloadComment represents comment in Transition payload +type TransitionPayloadComment struct { + Add TransitionPayloadCommentBody `json:"add,omitempty" structs:"add,omitempty"` +} + +// TransitionPayloadCommentBody represents body of comment in payload +type TransitionPayloadCommentBody struct { + Body string `json:"body,omitempty"` +} + +// TransitionPayload represents the request payload of Transition calls like DoTransition +type TransitionPayload struct { + ID string `json:"id" structs:"id"` +} + +// TransitionPayloadFields represents the fields that can be set when executing a transition +type TransitionPayloadFields struct { + Resolution *Resolution `json:"resolution,omitempty" structs:"resolution,omitempty"` +} + +// Option represents an option value in a SelectList or MultiSelect +// custom issue field +type Option struct { + Value string `json:"value" structs:"value"` +} + +// UnmarshalJSON will transform the Jira time into a time.Time +// during the transformation of the Jira JSON response +func (t *Time) UnmarshalJSON(b []byte) error { + // Ignore null, like in the main JSON package. + if string(b) == "null" { + return nil + } + ti, err := time.Parse("\"2006-01-02T15:04:05.999-0700\"", string(b)) + if err != nil { + return err + } + *t = Time(ti) + return nil +} + +// MarshalJSON will transform the time.Time into a Jira time +// during the creation of a Jira request +func (t Time) MarshalJSON() ([]byte, error) { + return []byte(time.Time(t).Format("\"2006-01-02T15:04:05.000-0700\"")), nil +} + +// UnmarshalJSON will transform the Jira date into a time.Time +// during the transformation of the Jira JSON response +func (t *Date) UnmarshalJSON(b []byte) error { + // Ignore null, like in the main JSON package. + if string(b) == "null" { + return nil + } + ti, err := time.Parse("\"2006-01-02\"", string(b)) + if err != nil { + return err + } + *t = Date(ti) + return nil +} + +// MarshalJSON will transform the Date object into a short +// date string as Jira expects during the creation of a +// Jira request +func (t Date) MarshalJSON() ([]byte, error) { + time := time.Time(t) + return []byte(time.Format("\"2006-01-02\"")), nil +} + +// Worklog represents the work log of a Jira issue. +// One Worklog contains zero or n WorklogRecords +// Jira Wiki: https://confluence.atlassian.com/jira/logging-work-on-an-issue-185729605.html +type Worklog struct { + StartAt int `json:"startAt" structs:"startAt"` + MaxResults int `json:"maxResults" structs:"maxResults"` + Total int `json:"total" structs:"total"` + Worklogs []WorklogRecord `json:"worklogs" structs:"worklogs"` +} + +// WorklogRecord represents one entry of a Worklog +type WorklogRecord struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + Author *User `json:"author,omitempty" structs:"author,omitempty"` + UpdateAuthor *User `json:"updateAuthor,omitempty" structs:"updateAuthor,omitempty"` + Comment string `json:"comment,omitempty" structs:"comment,omitempty"` + Created *Time `json:"created,omitempty" structs:"created,omitempty"` + Updated *Time `json:"updated,omitempty" structs:"updated,omitempty"` + Started *Time `json:"started,omitempty" structs:"started,omitempty"` + TimeSpent string `json:"timeSpent,omitempty" structs:"timeSpent,omitempty"` + TimeSpentSeconds int `json:"timeSpentSeconds,omitempty" structs:"timeSpentSeconds,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + IssueID string `json:"issueId,omitempty" structs:"issueId,omitempty"` + Properties []EntityProperty `json:"properties,omitempty"` +} + +type EntityProperty struct { + Key string `json:"key"` + Value interface{} `json:"value"` +} + +// TimeTracking represents the timetracking fields of a Jira issue. +type TimeTracking struct { + OriginalEstimate string `json:"originalEstimate,omitempty" structs:"originalEstimate,omitempty"` + RemainingEstimate string `json:"remainingEstimate,omitempty" structs:"remainingEstimate,omitempty"` + TimeSpent string `json:"timeSpent,omitempty" structs:"timeSpent,omitempty"` + OriginalEstimateSeconds int `json:"originalEstimateSeconds,omitempty" structs:"originalEstimateSeconds,omitempty"` + RemainingEstimateSeconds int `json:"remainingEstimateSeconds,omitempty" structs:"remainingEstimateSeconds,omitempty"` + TimeSpentSeconds int `json:"timeSpentSeconds,omitempty" structs:"timeSpentSeconds,omitempty"` +} + +// Subtasks represents all issues of a parent issue. +type Subtasks struct { + ID string `json:"id" structs:"id"` + Key string `json:"key" structs:"key"` + Self string `json:"self" structs:"self"` + Fields IssueFields `json:"fields" structs:"fields"` +} + +// IssueLink represents a link between two issues in Jira. +type IssueLink struct { + ID string `json:"id,omitempty" structs:"id,omitempty"` + Self string `json:"self,omitempty" structs:"self,omitempty"` + Type IssueLinkType `json:"type" structs:"type"` + OutwardIssue *Issue `json:"outwardIssue" structs:"outwardIssue"` + InwardIssue *Issue `json:"inwardIssue" structs:"inwardIssue"` + Comment *Comment `json:"comment,omitempty" structs:"comment,omitempty"` +} + +// IssueLinkType represents a type of a link between to issues in Jira. +// Typical issue link types are "Related to", "Duplicate", "Is blocked by", etc. +type IssueLinkType struct { + ID string `json:"id,omitempty" structs:"id,omitempty"` + Self string `json:"self,omitempty" structs:"self,omitempty"` + Name string `json:"name" structs:"name"` + Inward string `json:"inward" structs:"inward"` + Outward string `json:"outward" structs:"outward"` +} + +// Comments represents a list of Comment. +type Comments struct { + Comments []*Comment `json:"comments,omitempty" structs:"comments,omitempty"` +} + +// Comment represents a comment by a person to an issue in Jira. +type Comment struct { + ID string `json:"id,omitempty" structs:"id,omitempty"` + Self string `json:"self,omitempty" structs:"self,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Author User `json:"author,omitempty" structs:"author,omitempty"` + Body string `json:"body,omitempty" structs:"body,omitempty"` + UpdateAuthor User `json:"updateAuthor,omitempty" structs:"updateAuthor,omitempty"` + Updated string `json:"updated,omitempty" structs:"updated,omitempty"` + Created string `json:"created,omitempty" structs:"created,omitempty"` + Visibility CommentVisibility `json:"visibility,omitempty" structs:"visibility,omitempty"` +} + +// FixVersion represents a software release in which an issue is fixed. +type FixVersion struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` + Archived *bool `json:"archived,omitempty" structs:"archived,omitempty"` + Released *bool `json:"released,omitempty" structs:"released,omitempty"` + ReleaseDate string `json:"releaseDate,omitempty" structs:"releaseDate,omitempty"` + UserReleaseDate string `json:"userReleaseDate,omitempty" structs:"userReleaseDate,omitempty"` + ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"` // Unlike other IDs, this is returned as a number + StartDate string `json:"startDate,omitempty" structs:"startDate,omitempty"` +} + +// AffectsVersion represents a software release which is affected by an issue. +type AffectsVersion Version + +// CommentVisibility represents he visibility of a comment. +// E.g. Type could be "role" and Value "Administrators" +type CommentVisibility struct { + Type string `json:"type,omitempty" structs:"type,omitempty"` + Value string `json:"value,omitempty" structs:"value,omitempty"` +} + +// SearchOptions specifies the optional parameters to various List methods that +// support pagination. +// Pagination is used for the Jira REST APIs to conserve server resources and limit +// response size for resources that return potentially large collection of items. +// A request to a pages API will result in a values array wrapped in a JSON object with some paging metadata +// Default Pagination options +type SearchOptions struct { + // StartAt: The starting index of the returned projects. Base index: 0. + StartAt int `url:"startAt,omitempty"` + // MaxResults: The maximum number of projects to return per page. Default: 50. + MaxResults int `url:"maxResults,omitempty"` + // Expand: Expand specific sections in the returned issues + Expand string `url:"expand,omitempty"` + Fields []string + // ValidateQuery: The validateQuery param offers control over whether to validate and how strictly to treat the validation. Default: strict. + ValidateQuery string `url:"validateQuery,omitempty"` +} + +// searchResult is only a small wrapper around the Search (with JQL) method +// to be able to parse the results +type searchResult struct { + Issues []Issue `json:"issues" structs:"issues"` + StartAt int `json:"startAt" structs:"startAt"` + MaxResults int `json:"maxResults" structs:"maxResults"` + Total int `json:"total" structs:"total"` +} + +// GetQueryOptions specifies the optional parameters for the Get Issue methods +type GetQueryOptions struct { + // Fields is the list of fields to return for the issue. By default, all fields are returned. + Fields string `url:"fields,omitempty"` + Expand string `url:"expand,omitempty"` + // Properties is the list of properties to return for the issue. By default no properties are returned. + Properties string `url:"properties,omitempty"` + // FieldsByKeys if true then fields in issues will be referenced by keys instead of ids + FieldsByKeys bool `url:"fieldsByKeys,omitempty"` + UpdateHistory bool `url:"updateHistory,omitempty"` + ProjectKeys string `url:"projectKeys,omitempty"` +} + +// GetWorklogsQueryOptions specifies the optional parameters for the Get Worklogs method +type GetWorklogsQueryOptions struct { + StartAt int64 `url:"startAt,omitempty"` + MaxResults int32 `url:"maxResults,omitempty"` + StartedAfter int64 `url:"startedAfter,omitempty"` + Expand string `url:"expand,omitempty"` +} + +type AddWorklogQueryOptions struct { + NotifyUsers bool `url:"notifyUsers,omitempty"` + AdjustEstimate string `url:"adjustEstimate,omitempty"` + NewEstimate string `url:"newEstimate,omitempty"` + ReduceBy string `url:"reduceBy,omitempty"` + Expand string `url:"expand,omitempty"` + OverrideEditableFlag bool `url:"overrideEditableFlag,omitempty"` +} + +// CustomFields represents custom fields of Jira +// This can heavily differ between Jira instances +type CustomFields map[string]string + +// RemoteLink represents remote links which linked to issues +type RemoteLink struct { + ID int `json:"id,omitempty" structs:"id,omitempty"` + Self string `json:"self,omitempty" structs:"self,omitempty"` + GlobalID string `json:"globalId,omitempty" structs:"globalId,omitempty"` + Application *RemoteLinkApplication `json:"application,omitempty" structs:"application,omitempty"` + Relationship string `json:"relationship,omitempty" structs:"relationship,omitempty"` + Object *RemoteLinkObject `json:"object,omitempty" structs:"object,omitempty"` +} + +// RemoteLinkApplication represents remote links application +type RemoteLinkApplication struct { + Type string `json:"type,omitempty" structs:"type,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` +} + +// RemoteLinkObject represents remote link object itself +type RemoteLinkObject struct { + URL string `json:"url,omitempty" structs:"url,omitempty"` + Title string `json:"title,omitempty" structs:"title,omitempty"` + Summary string `json:"summary,omitempty" structs:"summary,omitempty"` + Icon *RemoteLinkIcon `json:"icon,omitempty" structs:"icon,omitempty"` + Status *RemoteLinkStatus `json:"status,omitempty" structs:"status,omitempty"` +} + +// RemoteLinkIcon represents icon displayed next to link +type RemoteLinkIcon struct { + Url16x16 string `json:"url16x16,omitempty" structs:"url16x16,omitempty"` + Title string `json:"title,omitempty" structs:"title,omitempty"` + Link string `json:"link,omitempty" structs:"link,omitempty"` +} + +// RemoteLinkStatus if the link is a resolvable object (issue, epic) - the structure represent its status +type RemoteLinkStatus struct { + Resolved bool `json:"resolved,omitempty" structs:"resolved,omitempty"` + Icon *RemoteLinkIcon `json:"icon,omitempty" structs:"icon,omitempty"` +} + +// GetWithContext returns a full representation of the issue for the given issue key. +// Jira will attempt to identify the issue by the issueIdOrKey path parameter. +// This can be an issue id, or an issue key. +// If the issue cannot be found via an exact match, Jira will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved. +// +// The given options will be appended to the query string +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getIssue +func (s *IssueService) GetWithContext(ctx context.Context, issueID string, options *GetQueryOptions) (*Issue, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + if options != nil { + q, err := query.Values(options) + if err != nil { + return nil, nil, err + } + req.URL.RawQuery = q.Encode() + } + + issue := new(Issue) + resp, err := s.client.Do(req, issue) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return issue, resp, nil +} + +// Get wraps GetWithContext using the background context. +func (s *IssueService) Get(issueID string, options *GetQueryOptions) (*Issue, *Response, error) { + return s.GetWithContext(context.Background(), issueID, options) +} + +// DownloadAttachmentWithContext returns a Response of an attachment for a given attachmentID. +// The attachment is in the Response.Body of the response. +// This is an io.ReadCloser. +// Caller must close resp.Body. +func (s *IssueService) DownloadAttachmentWithContext(ctx context.Context, attachmentID string) (*Response, error) { + apiEndpoint := fmt.Sprintf("secure/attachment/%s/", attachmentID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// DownloadAttachment wraps DownloadAttachmentWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) DownloadAttachment(attachmentID string) (*Response, error) { + return s.DownloadAttachmentWithContext(context.Background(), attachmentID) +} + +// PostAttachmentWithContext uploads r (io.Reader) as an attachment to a given issueID +func (s *IssueService) PostAttachmentWithContext(ctx context.Context, issueID string, r io.Reader, attachmentName string) (*[]Attachment, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/attachments", issueID) + + b := new(bytes.Buffer) + writer := multipart.NewWriter(b) + + fw, err := writer.CreateFormFile("file", attachmentName) + if err != nil { + return nil, nil, err + } + + if r != nil { + // Copy the file + if _, err = io.Copy(fw, r); err != nil { + return nil, nil, err + } + } + writer.Close() + + req, err := s.client.NewMultiPartRequestWithContext(ctx, "POST", apiEndpoint, b) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Content-Type", writer.FormDataContentType()) + + // PostAttachment response returns a JSON array (as multiple attachments can be posted) + attachment := new([]Attachment) + resp, err := s.client.Do(req, attachment) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return attachment, resp, nil +} + +// PostAttachment wraps PostAttachmentWithContext using the background context. +func (s *IssueService) PostAttachment(issueID string, r io.Reader, attachmentName string) (*[]Attachment, *Response, error) { + return s.PostAttachmentWithContext(context.Background(), issueID, r, attachmentName) +} + +// DeleteAttachmentWithContext deletes an attachment of a given attachmentID +// Caller must close resp.Body +func (s *IssueService) DeleteAttachmentWithContext(ctx context.Context, attachmentID string) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/attachment/%s", attachmentID) + + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// DeleteAttachment wraps DeleteAttachmentWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) DeleteAttachment(attachmentID string) (*Response, error) { + return s.DeleteAttachmentWithContext(context.Background(), attachmentID) +} + +// DeleteLinkWithContext deletes a link of a given linkID +// Caller must close resp.Body +func (s *IssueService) DeleteLinkWithContext(ctx context.Context, linkID string) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issueLink/%s", linkID) + + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// DeleteLink wraps DeleteLinkWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) DeleteLink(linkID string) (*Response, error) { + return s.DeleteLinkWithContext(context.Background(), linkID) +} + +// GetWorklogsWithContext gets all the worklogs for an issue. +// This method is especially important if you need to read all the worklogs, not just the first page. +// +// https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/worklog-getIssueWorklog +func (s *IssueService) GetWorklogsWithContext(ctx context.Context, issueID string, options ...func(*http.Request) error) (*Worklog, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog", issueID) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + for _, option := range options { + err = option(req) + if err != nil { + return nil, nil, err + } + } + + v := new(Worklog) + resp, err := s.client.Do(req, v) + return v, resp, err +} + +// GetWorklogs wraps GetWorklogsWithContext using the background context. +func (s *IssueService) GetWorklogs(issueID string, options ...func(*http.Request) error) (*Worklog, *Response, error) { + return s.GetWorklogsWithContext(context.Background(), issueID, options...) +} + +// Applies query options to http request. +// This helper is meant to be used with all "QueryOptions" structs. +func WithQueryOptions(options interface{}) func(*http.Request) error { + q, err := query.Values(options) + if err != nil { + return func(*http.Request) error { + return err + } + } + + return func(r *http.Request) error { + r.URL.RawQuery = q.Encode() + return nil + } +} + +// CreateWithContext creates an issue or a sub-task from a JSON representation. +// Creating a sub-task is similar to creating a regular issue, with two important differences: +// The issueType field must correspond to a sub-task issue type and you must provide a parent field in the issue create request containing the id or key of the parent issue. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-createIssues +func (s *IssueService) CreateWithContext(ctx context.Context, issue *Issue) (*Issue, *Response, error) { + apiEndpoint := "rest/api/2/issue" + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, issue) + if err != nil { + return nil, nil, err + } + resp, err := s.client.Do(req, nil) + if err != nil { + // incase of error return the resp for further inspection + return nil, resp, err + } + + responseIssue := new(Issue) + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, resp, fmt.Errorf("could not read the returned data") + } + err = json.Unmarshal(data, responseIssue) + if err != nil { + return nil, resp, fmt.Errorf("could not unmarshall the data into struct") + } + return responseIssue, resp, nil +} + +// Create wraps CreateWithContext using the background context. +func (s *IssueService) Create(issue *Issue) (*Issue, *Response, error) { + return s.CreateWithContext(context.Background(), issue) +} + +// UpdateWithOptionsWithContext updates an issue from a JSON representation, +// while also specifying query params. The issue is found by key. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue +// Caller must close resp.Body +func (s *IssueService) UpdateWithOptionsWithContext(ctx context.Context, issue *Issue, opts *UpdateQueryOptions) (*Issue, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", issue.Key) + url, err := addOptions(apiEndpoint, opts) + if err != nil { + return nil, nil, err + } + req, err := s.client.NewRequestWithContext(ctx, "PUT", url, issue) + if err != nil { + return nil, nil, err + } + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + // This is just to follow the rest of the API's convention of returning an issue. + // Returning the same pointer here is pointless, so we return a copy instead. + ret := *issue + return &ret, resp, nil +} + +// UpdateWithOptions wraps UpdateWithOptionsWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) UpdateWithOptions(issue *Issue, opts *UpdateQueryOptions) (*Issue, *Response, error) { + return s.UpdateWithOptionsWithContext(context.Background(), issue, opts) +} + +// UpdateWithContext updates an issue from a JSON representation. The issue is found by key. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue-editIssue +func (s *IssueService) UpdateWithContext(ctx context.Context, issue *Issue) (*Issue, *Response, error) { + return s.UpdateWithOptionsWithContext(ctx, issue, nil) +} + +// Update wraps UpdateWithContext using the background context. +func (s *IssueService) Update(issue *Issue) (*Issue, *Response, error) { + return s.UpdateWithContext(context.Background(), issue) +} + +// UpdateIssueWithContext updates an issue from a JSON representation. The issue is found by key. +// +// https://docs.atlassian.com/jira/REST/7.4.0/#api/2/issue-editIssue +// Caller must close resp.Body +func (s *IssueService) UpdateIssueWithContext(ctx context.Context, jiraID string, data map[string]interface{}) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%v", jiraID) + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, data) + if err != nil { + return nil, err + } + resp, err := s.client.Do(req, nil) + if err != nil { + return resp, err + } + + // This is just to follow the rest of the API's convention of returning an issue. + // Returning the same pointer here is pointless, so we return a copy instead. + return resp, nil +} + +// UpdateIssue wraps UpdateIssueWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) UpdateIssue(jiraID string, data map[string]interface{}) (*Response, error) { + return s.UpdateIssueWithContext(context.Background(), jiraID, data) +} + +// AddCommentWithContext adds a new comment to issueID. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-addComment +func (s *IssueService) AddCommentWithContext(ctx context.Context, issueID string, comment *Comment) (*Comment, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment", issueID) + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, comment) + if err != nil { + return nil, nil, err + } + + responseComment := new(Comment) + resp, err := s.client.Do(req, responseComment) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return responseComment, resp, nil +} + +// AddComment wraps AddCommentWithContext using the background context. +func (s *IssueService) AddComment(issueID string, comment *Comment) (*Comment, *Response, error) { + return s.AddCommentWithContext(context.Background(), issueID, comment) +} + +// UpdateCommentWithContext updates the body of a comment, identified by comment.ID, on the issueID. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/issue/{issueIdOrKey}/comment-updateComment +func (s *IssueService) UpdateCommentWithContext(ctx context.Context, issueID string, comment *Comment) (*Comment, *Response, error) { + reqBody := struct { + Body string `json:"body"` + }{ + Body: comment.Body, + } + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment/%s", issueID, comment.ID) + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, reqBody) + if err != nil { + return nil, nil, err + } + + responseComment := new(Comment) + resp, err := s.client.Do(req, responseComment) + if err != nil { + return nil, resp, err + } + + return responseComment, resp, nil +} + +// UpdateComment wraps UpdateCommentWithContext using the background context. +func (s *IssueService) UpdateComment(issueID string, comment *Comment) (*Comment, *Response, error) { + return s.UpdateCommentWithContext(context.Background(), issueID, comment) +} + +// DeleteCommentWithContext Deletes a comment from an issueID. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-issue-issueIdOrKey-comment-id-delete +func (s *IssueService) DeleteCommentWithContext(ctx context.Context, issueID, commentID string) error { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/comment/%s", issueID, commentID) + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) + if err != nil { + return err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return jerr + } + defer resp.Body.Close() + + return nil +} + +// DeleteComment wraps DeleteCommentWithContext using the background context. +func (s *IssueService) DeleteComment(issueID, commentID string) error { + return s.DeleteCommentWithContext(context.Background(), issueID, commentID) +} + +// AddWorklogRecordWithContext adds a new worklog record to issueID. +// +// https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-issueIdOrKey-worklog-post +func (s *IssueService) AddWorklogRecordWithContext(ctx context.Context, issueID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog", issueID) + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, record) + if err != nil { + return nil, nil, err + } + + for _, option := range options { + err = option(req) + if err != nil { + return nil, nil, err + } + } + + responseRecord := new(WorklogRecord) + resp, err := s.client.Do(req, responseRecord) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return responseRecord, resp, nil +} + +// AddWorklogRecord wraps AddWorklogRecordWithContext using the background context. +func (s *IssueService) AddWorklogRecord(issueID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) { + return s.AddWorklogRecordWithContext(context.Background(), issueID, record, options...) +} + +// UpdateWorklogRecordWithContext updates a worklog record. +// +// https://docs.atlassian.com/software/jira/docs/api/REST/7.1.2/#api/2/issue-updateWorklog +func (s *IssueService) UpdateWorklogRecordWithContext(ctx context.Context, issueID, worklogID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/worklog/%s", issueID, worklogID) + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, record) + if err != nil { + return nil, nil, err + } + + for _, option := range options { + err = option(req) + if err != nil { + return nil, nil, err + } + } + + responseRecord := new(WorklogRecord) + resp, err := s.client.Do(req, responseRecord) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return responseRecord, resp, nil +} + +// UpdateWorklogRecord wraps UpdateWorklogRecordWithContext using the background context. +func (s *IssueService) UpdateWorklogRecord(issueID, worklogID string, record *WorklogRecord, options ...func(*http.Request) error) (*WorklogRecord, *Response, error) { + return s.UpdateWorklogRecordWithContext(context.Background(), issueID, worklogID, record, options...) +} + +// AddLinkWithContext adds a link between two issues. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issueLink +// Caller must close resp.Body +func (s *IssueService) AddLinkWithContext(ctx context.Context, issueLink *IssueLink) (*Response, error) { + apiEndpoint := "rest/api/2/issueLink" + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, issueLink) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + err = NewJiraError(resp, err) + } + + return resp, err +} + +// AddLink wraps AddLinkWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) AddLink(issueLink *IssueLink) (*Response, error) { + return s.AddLinkWithContext(context.Background(), issueLink) +} + +// SearchWithContext will search for tickets according to the jql +// +// Jira API docs: https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-query-issues +func (s *IssueService) SearchWithContext(ctx context.Context, jql string, options *SearchOptions) ([]Issue, *Response, error) { + u := url.URL{ + Path: "rest/api/2/search", + } + uv := url.Values{} + if jql != "" { + uv.Add("jql", jql) + } + + if options != nil { + if options.StartAt != 0 { + uv.Add("startAt", strconv.Itoa(options.StartAt)) + } + if options.MaxResults != 0 { + uv.Add("maxResults", strconv.Itoa(options.MaxResults)) + } + if options.Expand != "" { + uv.Add("expand", options.Expand) + } + if strings.Join(options.Fields, ",") != "" { + uv.Add("fields", strings.Join(options.Fields, ",")) + } + if options.ValidateQuery != "" { + uv.Add("validateQuery", options.ValidateQuery) + } + } + + u.RawQuery = uv.Encode() + + req, err := s.client.NewRequestWithContext(ctx, "GET", u.String(), nil) + if err != nil { + return []Issue{}, nil, err + } + + v := new(searchResult) + resp, err := s.client.Do(req, v) + if err != nil { + err = NewJiraError(resp, err) + } + return v.Issues, resp, err +} + +// Search wraps SearchWithContext using the background context. +func (s *IssueService) Search(jql string, options *SearchOptions) ([]Issue, *Response, error) { + return s.SearchWithContext(context.Background(), jql, options) +} + +// SearchPagesWithContext will get issues from all pages in a search +// +// Jira API docs: https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-query-issues +func (s *IssueService) SearchPagesWithContext(ctx context.Context, jql string, options *SearchOptions, f func(Issue) error) error { + if options == nil { + options = &SearchOptions{ + StartAt: 0, + MaxResults: 50, + } + } + + if options.MaxResults == 0 { + options.MaxResults = 50 + } + + issues, resp, err := s.SearchWithContext(ctx, jql, options) + if err != nil { + return err + } + + if len(issues) == 0 { + return nil + } + + for { + for _, issue := range issues { + err = f(issue) + if err != nil { + return err + } + } + + if resp.StartAt+resp.MaxResults >= resp.Total { + return nil + } + + options.StartAt += resp.MaxResults + issues, resp, err = s.SearchWithContext(ctx, jql, options) + if err != nil { + return err + } + } +} + +// SearchPages wraps SearchPagesWithContext using the background context. +func (s *IssueService) SearchPages(jql string, options *SearchOptions, f func(Issue) error) error { + return s.SearchPagesWithContext(context.Background(), jql, options, f) +} + +// GetCustomFieldsWithContext returns a map of customfield_* keys with string values +func (s *IssueService) GetCustomFieldsWithContext(ctx context.Context, issueID string) (CustomFields, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + issue := new(map[string]interface{}) + resp, err := s.client.Do(req, issue) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + m := *issue + f := m["fields"] + cf := make(CustomFields) + if f == nil { + return cf, resp, nil + } + + if rec, ok := f.(map[string]interface{}); ok { + for key, val := range rec { + if strings.Contains(key, "customfield") { + if valMap, ok := val.(map[string]interface{}); ok { + if v, ok := valMap["value"]; ok { + val = v + } + } + cf[key] = fmt.Sprint(val) + } + } + } + return cf, resp, nil +} + +// GetCustomFields wraps GetCustomFieldsWithContext using the background context. +func (s *IssueService) GetCustomFields(issueID string) (CustomFields, *Response, error) { + return s.GetCustomFieldsWithContext(context.Background(), issueID) +} + +// GetTransitionsWithContext gets a list of the transitions possible for this issue by the current user, +// along with fields that are required and their types. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getTransitions +func (s *IssueService) GetTransitionsWithContext(ctx context.Context, id string) ([]Transition, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions?expand=transitions.fields", id) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + result := new(transitionResult) + resp, err := s.client.Do(req, result) + if err != nil { + err = NewJiraError(resp, err) + } + return result.Transitions, resp, err +} + +// GetTransitions wraps GetTransitionsWithContext using the background context. +func (s *IssueService) GetTransitions(id string) ([]Transition, *Response, error) { + return s.GetTransitionsWithContext(context.Background(), id) +} + +// DoTransitionWithContext performs a transition on an issue. +// When performing the transition you can update or set other issue fields. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition +func (s *IssueService) DoTransitionWithContext(ctx context.Context, ticketID, transitionID string) (*Response, error) { + payload := CreateTransitionPayload{ + Transition: TransitionPayload{ + ID: transitionID, + }, + } + return s.DoTransitionWithPayloadWithContext(ctx, ticketID, payload) +} + +// DoTransition wraps DoTransitionWithContext using the background context. +func (s *IssueService) DoTransition(ticketID, transitionID string) (*Response, error) { + return s.DoTransitionWithContext(context.Background(), ticketID, transitionID) +} + +// DoTransitionWithPayloadWithContext performs a transition on an issue using any payload. +// When performing the transition you can update or set other issue fields. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-doTransition +// Caller must close resp.Body +func (s *IssueService) DoTransitionWithPayloadWithContext(ctx context.Context, ticketID, payload interface{}) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/transitions", ticketID) + + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + err = NewJiraError(resp, err) + } + + return resp, err +} + +// DoTransitionWithPayload wraps DoTransitionWithPayloadWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) DoTransitionWithPayload(ticketID, payload interface{}) (*Response, error) { + return s.DoTransitionWithPayloadWithContext(context.Background(), ticketID, payload) +} + +// InitIssueWithMetaAndFields returns Issue with with values from fieldsConfig properly set. +// * metaProject should contain metaInformation about the project where the issue should be created. +// * metaIssuetype is the MetaInformation about the Issuetype that needs to be created. +// * fieldsConfig is a key->value pair where key represents the name of the field as seen in the UI +// And value is the string value for that particular key. +// Note: This method doesn't verify that the fieldsConfig is complete with mandatory fields. The fieldsConfig is +// supposed to be already verified with MetaIssueType.CheckCompleteAndAvailable. It will however return +// error if the key is not found. +// All values will be packed into Unknowns. This is much convenient. If the struct fields needs to be +// configured as well, marshalling and unmarshalling will set the proper fields. +func InitIssueWithMetaAndFields(metaProject *MetaProject, metaIssuetype *MetaIssueType, fieldsConfig map[string]string) (*Issue, error) { + issue := new(Issue) + issueFields := new(IssueFields) + issueFields.Unknowns = tcontainer.NewMarshalMap() + + // map the field names the User presented to jira's internal key + allFields, _ := metaIssuetype.GetAllFields() + for key, value := range fieldsConfig { + jiraKey, found := allFields[key] + if !found { + return nil, fmt.Errorf("key %s is not found in the list of fields", key) + } + + valueType, err := metaIssuetype.Fields.String(jiraKey + "/schema/type") + if err != nil { + return nil, err + } + switch valueType { + case "array": + elemType, err := metaIssuetype.Fields.String(jiraKey + "/schema/items") + if err != nil { + return nil, err + } + switch elemType { + case "component": + issueFields.Unknowns[jiraKey] = []Component{{Name: value}} + case "option": + issueFields.Unknowns[jiraKey] = []map[string]string{{"value": value}} + default: + issueFields.Unknowns[jiraKey] = []string{value} + } + case "string": + issueFields.Unknowns[jiraKey] = value + case "date": + issueFields.Unknowns[jiraKey] = value + case "datetime": + issueFields.Unknowns[jiraKey] = value + case "any": + // Treat any as string + issueFields.Unknowns[jiraKey] = value + case "project": + issueFields.Unknowns[jiraKey] = Project{ + Name: metaProject.Name, + ID: metaProject.Id, + } + case "priority": + issueFields.Unknowns[jiraKey] = Priority{Name: value} + case "user": + issueFields.Unknowns[jiraKey] = User{ + Name: value, + } + case "issuetype": + issueFields.Unknowns[jiraKey] = IssueType{ + Name: value, + } + case "option": + issueFields.Unknowns[jiraKey] = Option{ + Value: value, + } + default: + return nil, fmt.Errorf("unknown issue type encountered: %s for %s", valueType, key) + } + } + + issue.Fields = issueFields + + return issue, nil +} + +// DeleteWithContext will delete a specified issue. +// Caller must close resp.Body +func (s *IssueService) DeleteWithContext(ctx context.Context, issueID string) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s", issueID) + + // to enable deletion of subtasks; without this, the request will fail if the issue has subtasks + deletePayload := make(map[string]interface{}) + deletePayload["deleteSubtasks"] = "true" + content, _ := json.Marshal(deletePayload) + + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, content) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + return resp, err +} + +// Delete wraps DeleteWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) Delete(issueID string) (*Response, error) { + return s.DeleteWithContext(context.Background(), issueID) +} + +// GetWatchersWithContext wil return all the users watching/observing the given issue +// +// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-getIssueWatchers +func (s *IssueService) GetWatchersWithContext(ctx context.Context, issueID string) (*[]User, *Response, error) { + watchesAPIEndpoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID) + + req, err := s.client.NewRequestWithContext(ctx, "GET", watchesAPIEndpoint, nil) + if err != nil { + return nil, nil, err + } + + watches := new(Watches) + resp, err := s.client.Do(req, watches) + if err != nil { + return nil, nil, NewJiraError(resp, err) + } + + result := []User{} + for _, watcher := range watches.Watchers { + var user *User + if watcher.AccountID != "" { + user, resp, err = s.client.User.GetByAccountID(watcher.AccountID) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + } + result = append(result, *user) + } + + return &result, resp, nil +} + +// GetWatchers wraps GetWatchersWithContext using the background context. +func (s *IssueService) GetWatchers(issueID string) (*[]User, *Response, error) { + return s.GetWatchersWithContext(context.Background(), issueID) +} + +// AddWatcherWithContext adds watcher to the given issue +// +// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-addWatcher +// Caller must close resp.Body +func (s *IssueService) AddWatcherWithContext(ctx context.Context, issueID string, userName string) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID) + + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndPoint, userName) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + err = NewJiraError(resp, err) + } + + return resp, err +} + +// AddWatcher wraps AddWatcherWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) AddWatcher(issueID string, userName string) (*Response, error) { + return s.AddWatcherWithContext(context.Background(), issueID, userName) +} + +// RemoveWatcherWithContext removes given user from given issue +// +// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/latest/#api/2/issue-removeWatcher +// Caller must close resp.Body +func (s *IssueService) RemoveWatcherWithContext(ctx context.Context, issueID string, userName string) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/watchers", issueID) + + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, userName) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + err = NewJiraError(resp, err) + } + + return resp, err +} + +// RemoveWatcher wraps RemoveWatcherWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) RemoveWatcher(issueID string, userName string) (*Response, error) { + return s.RemoveWatcherWithContext(context.Background(), issueID, userName) +} + +// UpdateAssigneeWithContext updates the user assigned to work on the given issue +// +// Jira API docs: https://docs.atlassian.com/software/jira/docs/api/REST/7.10.2/#api/2/issue-assign +// Caller must close resp.Body +func (s *IssueService) UpdateAssigneeWithContext(ctx context.Context, issueID string, assignee *User) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/api/2/issue/%s/assignee", issueID) + + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndPoint, assignee) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + err = NewJiraError(resp, err) + } + + return resp, err +} + +// UpdateAssignee wraps UpdateAssigneeWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) UpdateAssignee(issueID string, assignee *User) (*Response, error) { + return s.UpdateAssigneeWithContext(context.Background(), issueID, assignee) +} + +func (c ChangelogHistory) CreatedTime() (time.Time, error) { + var t time.Time + // Ignore null + if string(c.Created) == "null" { + return t, nil + } + t, err := time.Parse("2006-01-02T15:04:05.999-0700", c.Created) + return t, err +} + +// GetRemoteLinksWithContext gets remote issue links on the issue. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/issue-getRemoteIssueLinks +func (s *IssueService) GetRemoteLinksWithContext(ctx context.Context, id string) (*[]RemoteLink, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/remotelink", id) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + result := new([]RemoteLink) + resp, err := s.client.Do(req, result) + if err != nil { + err = NewJiraError(resp, err) + } + return result, resp, err +} + +// GetRemoteLinks wraps GetRemoteLinksWithContext using the background context. +// Caller must close resp.Body +func (s *IssueService) GetRemoteLinks(id string) (*[]RemoteLink, *Response, error) { + return s.GetRemoteLinksWithContext(context.Background(), id) +} + +// AddRemoteLinkWithContext adds a remote link to issueID. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issue-issueIdOrKey-remotelink-post +func (s *IssueService) AddRemoteLinkWithContext(ctx context.Context, issueID string, remotelink *RemoteLink) (*RemoteLink, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/remotelink", issueID) + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, remotelink) + if err != nil { + return nil, nil, err + } + + responseRemotelink := new(RemoteLink) + resp, err := s.client.Do(req, responseRemotelink) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return responseRemotelink, resp, nil +} + +// AddRemoteLink wraps AddRemoteLinkWithContext using the background context. +func (s *IssueService) AddRemoteLink(issueID string, remotelink *RemoteLink) (*RemoteLink, *Response, error) { + return s.AddRemoteLinkWithContext(context.Background(), issueID, remotelink) +} + +// UpdateRemoteLinkWithContext updates a remote issue link by linkID. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/api-group-issue-remote-links/#api-rest-api-2-issue-issueidorkey-remotelink-linkid-put +func (s *IssueService) UpdateRemoteLinkWithContext(ctx context.Context, issueID string, linkID int, remotelink *RemoteLink) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issue/%s/remotelink/%d", issueID, linkID) + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, remotelink) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// UpdateRemoteLink wraps UpdateRemoteLinkWithContext using the background context. +func (s *IssueService) UpdateRemoteLink(issueID string, linkID int, remotelink *RemoteLink) (*Response, error) { + return s.UpdateRemoteLinkWithContext(context.Background(), issueID, linkID, remotelink) +} diff --git a/vendor/github.com/andygrunwald/go-jira/issuelinktype.go b/vendor/github.com/andygrunwald/go-jira/issuelinktype.go new file mode 100644 index 0000000000..24a3ab0e63 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/issuelinktype.go @@ -0,0 +1,141 @@ +package jira + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" +) + +// IssueLinkTypeService handles issue link types for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Issue-link-types +type IssueLinkTypeService struct { + client *Client +} + +// GetListWithContext gets all of the issue link types from Jira. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-get +func (s *IssueLinkTypeService) GetListWithContext(ctx context.Context) ([]IssueLinkType, *Response, error) { + apiEndpoint := "rest/api/2/issueLinkType" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + linkTypeList := []IssueLinkType{} + resp, err := s.client.Do(req, &linkTypeList) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return linkTypeList, resp, nil +} + +// GetList wraps GetListWithContext using the background context. +func (s *IssueLinkTypeService) GetList() ([]IssueLinkType, *Response, error) { + return s.GetListWithContext(context.Background()) +} + +// GetWithContext gets info of a specific issue link type from Jira. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-get +func (s *IssueLinkTypeService) GetWithContext(ctx context.Context, ID string) (*IssueLinkType, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil) + if err != nil { + return nil, nil, err + } + + linkType := new(IssueLinkType) + resp, err := s.client.Do(req, linkType) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return linkType, resp, nil +} + +// Get wraps GetWithContext using the background context. +func (s *IssueLinkTypeService) Get(ID string) (*IssueLinkType, *Response, error) { + return s.GetWithContext(context.Background(), ID) +} + +// CreateWithContext creates an issue link type in Jira. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-post +func (s *IssueLinkTypeService) CreateWithContext(ctx context.Context, linkType *IssueLinkType) (*IssueLinkType, *Response, error) { + apiEndpoint := "/rest/api/2/issueLinkType" + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, linkType) + if err != nil { + return nil, nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return nil, resp, err + } + + responseLinkType := new(IssueLinkType) + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + e := fmt.Errorf("could not read the returned data") + return nil, resp, NewJiraError(resp, e) + } + err = json.Unmarshal(data, responseLinkType) + if err != nil { + e := fmt.Errorf("could no unmarshal the data into struct") + return nil, resp, NewJiraError(resp, e) + } + return linkType, resp, nil +} + +// Create wraps CreateWithContext using the background context. +func (s *IssueLinkTypeService) Create(linkType *IssueLinkType) (*IssueLinkType, *Response, error) { + return s.CreateWithContext(context.Background(), linkType) +} + +// UpdateWithContext updates an issue link type. The issue is found by key. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-put +// Caller must close resp.Body +func (s *IssueLinkTypeService) UpdateWithContext(ctx context.Context, linkType *IssueLinkType) (*IssueLinkType, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", linkType.ID) + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, linkType) + if err != nil { + return nil, nil, err + } + resp, err := s.client.Do(req, nil) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + ret := *linkType + return &ret, resp, nil +} + +// Update wraps UpdateWithContext using the background context. +// Caller must close resp.Body +func (s *IssueLinkTypeService) Update(linkType *IssueLinkType) (*IssueLinkType, *Response, error) { + return s.UpdateWithContext(context.Background(), linkType) +} + +// DeleteWithContext deletes an issue link type based on provided ID. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-issueLinkType-issueLinkTypeId-delete +// Caller must close resp.Body +func (s *IssueLinkTypeService) DeleteWithContext(ctx context.Context, ID string) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/issueLinkType/%s", ID) + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + return resp, err +} + +// Delete wraps DeleteWithContext using the background context. +// Caller must close resp.Body +func (s *IssueLinkTypeService) Delete(ID string) (*Response, error) { + return s.DeleteWithContext(context.Background(), ID) +} diff --git a/vendor/github.com/andygrunwald/go-jira/jira.go b/vendor/github.com/andygrunwald/go-jira/jira.go new file mode 100644 index 0000000000..25c52bae52 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/jira.go @@ -0,0 +1,641 @@ +package jira + +import ( + "bytes" + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "reflect" + "sort" + "strings" + "time" + + jwt "github.com/golang-jwt/jwt/v4" + "github.com/google/go-querystring/query" + "github.com/pkg/errors" +) + +// httpClient defines an interface for an http.Client implementation so that alternative +// http Clients can be passed in for making requests +type httpClient interface { + Do(request *http.Request) (response *http.Response, err error) +} + +// A Client manages communication with the Jira API. +type Client struct { + // HTTP client used to communicate with the API. + client httpClient + + // Base URL for API requests. + baseURL *url.URL + + // Session storage if the user authenticates with a Session cookie + session *Session + + // Services used for talking to different parts of the Jira API. + Authentication *AuthenticationService + Issue *IssueService + Project *ProjectService + Board *BoardService + Sprint *SprintService + User *UserService + Group *GroupService + Version *VersionService + Priority *PriorityService + Field *FieldService + Component *ComponentService + Resolution *ResolutionService + StatusCategory *StatusCategoryService + Filter *FilterService + Role *RoleService + PermissionScheme *PermissionSchemeService + Status *StatusService + IssueLinkType *IssueLinkTypeService + Organization *OrganizationService + ServiceDesk *ServiceDeskService + Customer *CustomerService + Request *RequestService +} + +// NewClient returns a new Jira API client. +// If a nil httpClient is provided, http.DefaultClient will be used. +// To use API methods which require authentication you can follow the preferred solution and +// provide an http.Client that will perform the authentication for you with OAuth and HTTP Basic (such as that provided by the golang.org/x/oauth2 library). +// As an alternative you can use Session Cookie based authentication provided by this package as well. +// See https://docs.atlassian.com/jira/REST/latest/#authentication +// baseURL is the HTTP endpoint of your Jira instance and should always be specified with a trailing slash. +func NewClient(httpClient httpClient, baseURL string) (*Client, error) { + if httpClient == nil { + httpClient = http.DefaultClient + } + + // ensure the baseURL contains a trailing slash so that all paths are preserved in later calls + if !strings.HasSuffix(baseURL, "/") { + baseURL += "/" + } + + parsedBaseURL, err := url.Parse(baseURL) + if err != nil { + return nil, err + } + + c := &Client{ + client: httpClient, + baseURL: parsedBaseURL, + } + c.Authentication = &AuthenticationService{client: c} + c.Issue = &IssueService{client: c} + c.Project = &ProjectService{client: c} + c.Board = &BoardService{client: c} + c.Sprint = &SprintService{client: c} + c.User = &UserService{client: c} + c.Group = &GroupService{client: c} + c.Version = &VersionService{client: c} + c.Priority = &PriorityService{client: c} + c.Field = &FieldService{client: c} + c.Component = &ComponentService{client: c} + c.Resolution = &ResolutionService{client: c} + c.StatusCategory = &StatusCategoryService{client: c} + c.Filter = &FilterService{client: c} + c.Role = &RoleService{client: c} + c.PermissionScheme = &PermissionSchemeService{client: c} + c.Status = &StatusService{client: c} + c.IssueLinkType = &IssueLinkTypeService{client: c} + c.Organization = &OrganizationService{client: c} + c.ServiceDesk = &ServiceDeskService{client: c} + c.Customer = &CustomerService{client: c} + c.Request = &RequestService{client: c} + + return c, nil +} + +// NewRawRequestWithContext creates an API request. +// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client. +// Allows using an optional native io.Reader for sourcing the request body. +func (c *Client) NewRawRequestWithContext(ctx context.Context, method, urlStr string, body io.Reader) (*http.Request, error) { + rel, err := url.Parse(urlStr) + if err != nil { + return nil, err + } + // Relative URLs should be specified without a preceding slash since baseURL will have the trailing slash + rel.Path = strings.TrimLeft(rel.Path, "/") + + u := c.baseURL.ResolveReference(rel) + + req, err := newRequestWithContext(ctx, method, u.String(), body) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/json") + + // Set authentication information + if c.Authentication.authType == authTypeSession { + // Set session cookie if there is one + if c.session != nil { + for _, cookie := range c.session.Cookies { + req.AddCookie(cookie) + } + } + } else if c.Authentication.authType == authTypeBasic { + // Set basic auth information + if c.Authentication.username != "" { + req.SetBasicAuth(c.Authentication.username, c.Authentication.password) + } + } + + return req, nil +} + +// NewRawRequest wraps NewRawRequestWithContext using the background context. +func (c *Client) NewRawRequest(method, urlStr string, body io.Reader) (*http.Request, error) { + return c.NewRawRequestWithContext(context.Background(), method, urlStr, body) +} + +// NewRequestWithContext creates an API request. +// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client. +// If specified, the value pointed to by body is JSON encoded and included as the request body. +func (c *Client) NewRequestWithContext(ctx context.Context, method, urlStr string, body interface{}) (*http.Request, error) { + rel, err := url.Parse(urlStr) + if err != nil { + return nil, err + } + // Relative URLs should be specified without a preceding slash since baseURL will have the trailing slash + rel.Path = strings.TrimLeft(rel.Path, "/") + + u := c.baseURL.ResolveReference(rel) + + var buf io.ReadWriter + if body != nil { + buf = new(bytes.Buffer) + err = json.NewEncoder(buf).Encode(body) + if err != nil { + return nil, err + } + } + + req, err := newRequestWithContext(ctx, method, u.String(), buf) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/json") + + // Set authentication information + if c.Authentication.authType == authTypeSession { + // Set session cookie if there is one + if c.session != nil { + for _, cookie := range c.session.Cookies { + req.AddCookie(cookie) + } + } + } else if c.Authentication.authType == authTypeBasic { + // Set basic auth information + if c.Authentication.username != "" { + req.SetBasicAuth(c.Authentication.username, c.Authentication.password) + } + } + + return req, nil +} + +// NewRequest wraps NewRequestWithContext using the background context. +func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) { + return c.NewRequestWithContext(context.Background(), method, urlStr, body) +} + +// addOptions adds the parameters in opt as URL query parameters to s. opt +// must be a struct whose fields may contain "url" tags. +func addOptions(s string, opt interface{}) (string, error) { + v := reflect.ValueOf(opt) + if v.Kind() == reflect.Ptr && v.IsNil() { + return s, nil + } + + u, err := url.Parse(s) + if err != nil { + return s, err + } + + qs, err := query.Values(opt) + if err != nil { + return s, err + } + + u.RawQuery = qs.Encode() + return u.String(), nil +} + +// NewMultiPartRequestWithContext creates an API request including a multi-part file. +// A relative URL can be provided in urlStr, in which case it is resolved relative to the baseURL of the Client. +// If specified, the value pointed to by buf is a multipart form. +func (c *Client) NewMultiPartRequestWithContext(ctx context.Context, method, urlStr string, buf *bytes.Buffer) (*http.Request, error) { + rel, err := url.Parse(urlStr) + if err != nil { + return nil, err + } + // Relative URLs should be specified without a preceding slash since baseURL will have the trailing slash + rel.Path = strings.TrimLeft(rel.Path, "/") + + u := c.baseURL.ResolveReference(rel) + + req, err := newRequestWithContext(ctx, method, u.String(), buf) + if err != nil { + return nil, err + } + + // Set required headers + req.Header.Set("X-Atlassian-Token", "nocheck") + + // Set authentication information + if c.Authentication.authType == authTypeSession { + // Set session cookie if there is one + if c.session != nil { + for _, cookie := range c.session.Cookies { + req.AddCookie(cookie) + } + } + } else if c.Authentication.authType == authTypeBasic { + // Set basic auth information + if c.Authentication.username != "" { + req.SetBasicAuth(c.Authentication.username, c.Authentication.password) + } + } + + return req, nil +} + +// NewMultiPartRequest wraps NewMultiPartRequestWithContext using the background context. +func (c *Client) NewMultiPartRequest(method, urlStr string, buf *bytes.Buffer) (*http.Request, error) { + return c.NewMultiPartRequestWithContext(context.Background(), method, urlStr, buf) +} + +// Do sends an API request and returns the API response. +// The API response is JSON decoded and stored in the value pointed to by v, or returned as an error if an API error has occurred. +func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) { + httpResp, err := c.client.Do(req) + if err != nil { + return nil, err + } + + err = CheckResponse(httpResp) + if err != nil { + // Even though there was an error, we still return the response + // in case the caller wants to inspect it further + return newResponse(httpResp, nil), err + } + + if v != nil { + // Open a NewDecoder and defer closing the reader only if there is a provided interface to decode to + defer httpResp.Body.Close() + err = json.NewDecoder(httpResp.Body).Decode(v) + } + + resp := newResponse(httpResp, v) + return resp, err +} + +// CheckResponse checks the API response for errors, and returns them if present. +// A response is considered an error if it has a status code outside the 200 range. +// The caller is responsible to analyze the response body. +// The body can contain JSON (if the error is intended) or xml (sometimes Jira just failes). +func CheckResponse(r *http.Response) error { + if c := r.StatusCode; 200 <= c && c <= 299 { + return nil + } + + err := fmt.Errorf("request failed. Please analyze the request body for more details. Status code: %d", r.StatusCode) + return err +} + +// GetBaseURL will return you the Base URL. +// This is the same URL as in the NewClient constructor +func (c *Client) GetBaseURL() url.URL { + return *c.baseURL +} + +// Response represents Jira API response. It wraps http.Response returned from +// API and provides information about paging. +type Response struct { + *http.Response + + StartAt int + MaxResults int + Total int +} + +func newResponse(r *http.Response, v interface{}) *Response { + resp := &Response{Response: r} + resp.populatePageValues(v) + return resp +} + +// Sets paging values if response json was parsed to searchResult type +// (can be extended with other types if they also need paging info) +func (r *Response) populatePageValues(v interface{}) { + switch value := v.(type) { + case *searchResult: + r.StartAt = value.StartAt + r.MaxResults = value.MaxResults + r.Total = value.Total + case *groupMembersResult: + r.StartAt = value.StartAt + r.MaxResults = value.MaxResults + r.Total = value.Total + } +} + +// BasicAuthTransport is an http.RoundTripper that authenticates all requests +// using HTTP Basic Authentication with the provided username and password. +type BasicAuthTransport struct { + Username string + Password string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. We just add the +// basic auth and return the RoundTripper for this transport type. +func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := cloneRequest(req) // per RoundTripper contract + + req2.SetBasicAuth(t.Username, t.Password) + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. This is a nice little bit of sugar +// so we can just get the client instead of creating the client in the calling code. +// If it's necessary to send more information on client init, the calling code can +// always skip this and set the transport itself. +func (t *BasicAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *BasicAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// BearerAuthTransport is a http.RoundTripper that authenticates all requests +// using Jira's bearer (oauth 2.0 (3lo)) based authentication. +type BearerAuthTransport struct { + Token string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. We just add the +// bearer token and return the RoundTripper for this transport type. +func (t *BearerAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := cloneRequest(req) // per RoundTripper contract + + req2.Header.Set("Authorization", fmt.Sprintf("Bearer %s", t.Token)) + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. This is a nice little bit of sugar +// so we can just get the client instead of creating the client in the calling code. +// If it's necessary to send more information on client init, the calling code can +// always skip this and set the transport itself. +func (t *BearerAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *BearerAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// PATAuthTransport is an http.RoundTripper that authenticates all requests +// using the Personal Access Token specified. +// See here for more info: https://confluence.atlassian.com/enterprise/using-personal-access-tokens-1026032365.html +type PATAuthTransport struct { + // Token is the key that was provided by Jira when creating the Personal Access Token. + Token string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. We just add the +// basic auth and return the RoundTripper for this transport type. +func (t *PATAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := cloneRequest(req) // per RoundTripper contract + req2.Header.Set("Authorization", "Bearer "+t.Token) + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. This is a nice little bit of sugar +// so we can just get the client instead of creating the client in the calling code. +// If it's necessary to send more information on client init, the calling code can +// always skip this and set the transport itself. +func (t *PATAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *PATAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// CookieAuthTransport is an http.RoundTripper that authenticates all requests +// using Jira's cookie-based authentication. +// +// Note that it is generally preferable to use HTTP BASIC authentication with the REST API. +// However, this resource may be used to mimic the behaviour of Jira's log-in page (e.g. to display log-in errors to a user). +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#auth/1/session +type CookieAuthTransport struct { + Username string + Password string + AuthURL string + + // SessionObject is the authenticated cookie string.s + // It's passed in each call to prove the client is authenticated. + SessionObject []*http.Cookie + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip adds the session object to the request. +func (t *CookieAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if t.SessionObject == nil { + err := t.setSessionObject() + if err != nil { + return nil, errors.Wrap(err, "cookieauth: no session object has been set") + } + } + + req2 := cloneRequest(req) // per RoundTripper contract + for _, cookie := range t.SessionObject { + // Don't add an empty value cookie to the request + if cookie.Value != "" { + req2.AddCookie(cookie) + } + } + + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using cookie authentication +func (t *CookieAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +// setSessionObject attempts to authenticate the user and set +// the session object (e.g. cookie) +func (t *CookieAuthTransport) setSessionObject() error { + req, err := t.buildAuthRequest() + if err != nil { + return err + } + + var authClient = &http.Client{ + Timeout: time.Second * 60, + } + resp, err := authClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + t.SessionObject = resp.Cookies() + return nil +} + +// getAuthRequest assembles the request to get the authenticated cookie +func (t *CookieAuthTransport) buildAuthRequest() (*http.Request, error) { + body := struct { + Username string `json:"username"` + Password string `json:"password"` + }{ + t.Username, + t.Password, + } + + b := new(bytes.Buffer) + json.NewEncoder(b).Encode(body) + + req, err := http.NewRequest("POST", t.AuthURL, b) + if err != nil { + return nil, err + } + + req.Header.Set("Content-Type", "application/json") + return req, nil +} + +func (t *CookieAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// JWTAuthTransport is an http.RoundTripper that authenticates all requests +// using Jira's JWT based authentication. +// +// NOTE: this form of auth should be used by add-ons installed from the Atlassian marketplace. +// +// Jira docs: https://developer.atlassian.com/cloud/jira/platform/understanding-jwt +// Examples in other languages: +// https://bitbucket.org/atlassian/atlassian-jwt-ruby/src/d44a8e7a4649e4f23edaa784402655fda7c816ea/lib/atlassian/jwt.rb +// https://bitbucket.org/atlassian/atlassian-jwt-py/src/master/atlassian_jwt/url_utils.py +type JWTAuthTransport struct { + Secret []byte + Issuer string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +func (t *JWTAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *JWTAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// RoundTrip adds the session object to the request. +func (t *JWTAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := cloneRequest(req) // per RoundTripper contract + exp := time.Duration(59) * time.Second + qsh := t.createQueryStringHash(req.Method, req2.URL) + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "iss": t.Issuer, + "iat": time.Now().Unix(), + "exp": time.Now().Add(exp).Unix(), + "qsh": qsh, + }) + + jwtStr, err := token.SignedString(t.Secret) + if err != nil { + return nil, errors.Wrap(err, "jwtAuth: error signing JWT") + } + + req2.Header.Set("Authorization", fmt.Sprintf("JWT %s", jwtStr)) + return t.transport().RoundTrip(req2) +} + +func (t *JWTAuthTransport) createQueryStringHash(httpMethod string, jiraURL *url.URL) string { + canonicalRequest := t.canonicalizeRequest(httpMethod, jiraURL) + h := sha256.Sum256([]byte(canonicalRequest)) + return hex.EncodeToString(h[:]) +} + +func (t *JWTAuthTransport) canonicalizeRequest(httpMethod string, jiraURL *url.URL) string { + path := "/" + strings.Replace(strings.Trim(jiraURL.Path, "/"), "&", "%26", -1) + + var canonicalQueryString []string + for k, v := range jiraURL.Query() { + if k == "jwt" { + continue + } + param := url.QueryEscape(k) + value := url.QueryEscape(strings.Join(v, "")) + canonicalQueryString = append(canonicalQueryString, strings.Replace(strings.Join([]string{param, value}, "="), "+", "%20", -1)) + } + sort.Strings(canonicalQueryString) + return fmt.Sprintf("%s&%s&%s", strings.ToUpper(httpMethod), path, strings.Join(canonicalQueryString, "&")) +} + +// cloneRequest returns a clone of the provided *http.Request. +// The clone is a shallow copy of the struct and its Header map. +func cloneRequest(r *http.Request) *http.Request { + // shallow copy of the struct + r2 := new(http.Request) + *r2 = *r + // deep copy of the Header + r2.Header = make(http.Header, len(r.Header)) + for k, s := range r.Header { + r2.Header[k] = append([]string(nil), s...) + } + return r2 +} diff --git a/vendor/github.com/andygrunwald/go-jira/metaissue.go b/vendor/github.com/andygrunwald/go-jira/metaissue.go new file mode 100644 index 0000000000..560a2f05a9 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/metaissue.go @@ -0,0 +1,234 @@ +package jira + +import ( + "context" + "fmt" + "strings" + + "github.com/google/go-querystring/query" + "github.com/trivago/tgo/tcontainer" +) + +// CreateMetaInfo contains information about fields and their attributed to create a ticket. +type CreateMetaInfo struct { + Expand string `json:"expand,omitempty"` + Projects []*MetaProject `json:"projects,omitempty"` +} + +// EditMetaInfo contains information about fields and their attributed to edit a ticket. +type EditMetaInfo struct { + Fields tcontainer.MarshalMap `json:"fields,omitempty"` +} + +// MetaProject is the meta information about a project returned from createmeta api +type MetaProject struct { + Expand string `json:"expand,omitempty"` + Self string `json:"self,omitempty"` + Id string `json:"id,omitempty"` + Key string `json:"key,omitempty"` + Name string `json:"name,omitempty"` + // omitted avatarUrls + IssueTypes []*MetaIssueType `json:"issuetypes,omitempty"` +} + +// MetaIssueType represents the different issue types a project has. +// +// Note: Fields is interface because this is an object which can +// have arbitraty keys related to customfields. It is not possible to +// expect these for a general way. This will be returning a map. +// Further processing must be done depending on what is required. +type MetaIssueType struct { + Self string `json:"self,omitempty"` + Id string `json:"id,omitempty"` + Description string `json:"description,omitempty"` + IconUrl string `json:"iconurl,omitempty"` + Name string `json:"name,omitempty"` + Subtasks bool `json:"subtask,omitempty"` + Expand string `json:"expand,omitempty"` + Fields tcontainer.MarshalMap `json:"fields,omitempty"` +} + +// GetCreateMetaWithContext makes the api call to get the meta information required to create a ticket +func (s *IssueService) GetCreateMetaWithContext(ctx context.Context, projectkeys string) (*CreateMetaInfo, *Response, error) { + return s.GetCreateMetaWithOptionsWithContext(ctx, &GetQueryOptions{ProjectKeys: projectkeys, Expand: "projects.issuetypes.fields"}) +} + +// GetCreateMeta wraps GetCreateMetaWithContext using the background context. +func (s *IssueService) GetCreateMeta(projectkeys string) (*CreateMetaInfo, *Response, error) { + return s.GetCreateMetaWithContext(context.Background(), projectkeys) +} + +// GetCreateMetaWithOptionsWithContext makes the api call to get the meta information without requiring to have a projectKey +func (s *IssueService) GetCreateMetaWithOptionsWithContext(ctx context.Context, options *GetQueryOptions) (*CreateMetaInfo, *Response, error) { + apiEndpoint := "rest/api/2/issue/createmeta" + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + if options != nil { + q, err := query.Values(options) + if err != nil { + return nil, nil, err + } + req.URL.RawQuery = q.Encode() + } + + meta := new(CreateMetaInfo) + resp, err := s.client.Do(req, meta) + + if err != nil { + return nil, resp, err + } + + return meta, resp, nil +} + +// GetCreateMetaWithOptions wraps GetCreateMetaWithOptionsWithContext using the background context. +func (s *IssueService) GetCreateMetaWithOptions(options *GetQueryOptions) (*CreateMetaInfo, *Response, error) { + return s.GetCreateMetaWithOptionsWithContext(context.Background(), options) +} + +// GetEditMetaWithContext makes the api call to get the edit meta information for an issue +func (s *IssueService) GetEditMetaWithContext(ctx context.Context, issue *Issue) (*EditMetaInfo, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/issue/%s/editmeta", issue.Key) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + meta := new(EditMetaInfo) + resp, err := s.client.Do(req, meta) + + if err != nil { + return nil, resp, err + } + + return meta, resp, nil +} + +// GetEditMeta wraps GetEditMetaWithContext using the background context. +func (s *IssueService) GetEditMeta(issue *Issue) (*EditMetaInfo, *Response, error) { + return s.GetEditMetaWithContext(context.Background(), issue) +} + +// GetProjectWithName returns a project with "name" from the meta information received. If not found, this returns nil. +// The comparison of the name is case insensitive. +func (m *CreateMetaInfo) GetProjectWithName(name string) *MetaProject { + for _, m := range m.Projects { + if strings.EqualFold(m.Name, name) { + return m + } + } + return nil +} + +// GetProjectWithKey returns a project with "name" from the meta information received. If not found, this returns nil. +// The comparison of the name is case insensitive. +func (m *CreateMetaInfo) GetProjectWithKey(key string) *MetaProject { + for _, m := range m.Projects { + if strings.EqualFold(m.Key, key) { + return m + } + } + return nil +} + +// GetIssueTypeWithName returns an IssueType with name from a given MetaProject. If not found, this returns nil. +// The comparison of the name is case insensitive +func (p *MetaProject) GetIssueTypeWithName(name string) *MetaIssueType { + for _, m := range p.IssueTypes { + if strings.EqualFold(m.Name, name) { + return m + } + } + return nil +} + +// GetMandatoryFields returns a map of all the required fields from the MetaIssueTypes. +// if a field returned by the api was: +// "customfield_10806": { +// "required": true, +// "schema": { +// "type": "any", +// "custom": "com.pyxis.greenhopper.jira:gh-epic-link", +// "customId": 10806 +// }, +// "name": "Epic Link", +// "hasDefaultValue": false, +// "operations": [ +// "set" +// ] +// } +// the returned map would have "Epic Link" as the key and "customfield_10806" as value. +// This choice has been made so that the it is easier to generate the create api request later. +func (t *MetaIssueType) GetMandatoryFields() (map[string]string, error) { + ret := make(map[string]string) + for key := range t.Fields { + required, err := t.Fields.Bool(key + "/required") + if err != nil { + return nil, err + } + if required { + name, err := t.Fields.String(key + "/name") + if err != nil { + return nil, err + } + ret[name] = key + } + } + return ret, nil +} + +// GetAllFields returns a map of all the fields for an IssueType. This includes all required and not required. +// The key of the returned map is what you see in the form and the value is how it is representated in the jira schema. +func (t *MetaIssueType) GetAllFields() (map[string]string, error) { + ret := make(map[string]string) + for key := range t.Fields { + + name, err := t.Fields.String(key + "/name") + if err != nil { + return nil, err + } + ret[name] = key + } + return ret, nil +} + +// CheckCompleteAndAvailable checks if the given fields satisfies the mandatory field required to create a issue for the given type +// And also if the given fields are available. +func (t *MetaIssueType) CheckCompleteAndAvailable(config map[string]string) (bool, error) { + mandatory, err := t.GetMandatoryFields() + if err != nil { + return false, err + } + all, err := t.GetAllFields() + if err != nil { + return false, err + } + + // check templateconfig against mandatory fields + for key := range mandatory { + if _, okay := config[key]; !okay { + var requiredFields []string + for name := range mandatory { + requiredFields = append(requiredFields, name) + } + return false, fmt.Errorf("required field not found in provided jira.fields. Required are: %#v", requiredFields) + } + } + + // check templateConfig against all fields to verify they are available + for key := range config { + if _, okay := all[key]; !okay { + var availableFields []string + for name := range all { + availableFields = append(availableFields, name) + } + return false, fmt.Errorf("fields in jira.fields are not available in jira. Available are: %#v", availableFields) + } + } + + return true, nil +} diff --git a/vendor/github.com/andygrunwald/go-jira/organization.go b/vendor/github.com/andygrunwald/go-jira/organization.go new file mode 100644 index 0000000000..65f222b3e6 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/organization.go @@ -0,0 +1,397 @@ +package jira + +import ( + "context" + "fmt" +) + +// OrganizationService handles Organizations for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/ +type OrganizationService struct { + client *Client +} + +// OrganizationCreationDTO is DTO for creat organization API +type OrganizationCreationDTO struct { + Name string `json:"name,omitempty" structs:"name,omitempty"` +} + +// SelfLink Stores REST API URL to the organization. +type SelfLink struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` +} + +// Organization contains Organization data +type Organization struct { + ID string `json:"id,omitempty" structs:"id,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"` +} + +// OrganizationUsersDTO contains organization user ids +type OrganizationUsersDTO struct { + AccountIds []string `json:"accountIds,omitempty" structs:"accountIds,omitempty"` +} + +// PagedDTO is response of a paged list +type PagedDTO struct { + Size int `json:"size,omitempty" structs:"size,omitempty"` + Start int `json:"start,omitempty" structs:"start,omitempty"` + Limit int `limit:"size,omitempty" structs:"limit,omitempty"` + IsLastPage bool `json:"isLastPage,omitempty" structs:"isLastPage,omitempty"` + Values []interface{} `values:"isLastPage,omitempty" structs:"values,omitempty"` + Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"` +} + +// PropertyKey contains Property key details. +type PropertyKey struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + Key string `json:"key,omitempty" structs:"key,omitempty"` +} + +// PropertyKeys contains an array of PropertyKey +type PropertyKeys struct { + Keys []PropertyKey `json:"keys,omitempty" structs:"keys,omitempty"` +} + +// GetAllOrganizationsWithContext returns a list of organizations in +// the Jira Service Management instance. +// Use this method when you want to present a list +// of organizations or want to locate an organization +// by name. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-group-organization +func (s *OrganizationService) GetAllOrganizationsWithContext(ctx context.Context, start int, limit int, accountID string) (*PagedDTO, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization?start=%d&limit=%d", start, limit) + if accountID != "" { + apiEndPoint += fmt.Sprintf("&accountId=%s", accountID) + } + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, nil, err + } + + v := new(PagedDTO) + resp, err := s.client.Do(req, v) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return v, resp, nil +} + +// GetAllOrganizations wraps GetAllOrganizationsWithContext using the background context. +func (s *OrganizationService) GetAllOrganizations(start int, limit int, accountID string) (*PagedDTO, *Response, error) { + return s.GetAllOrganizationsWithContext(context.Background(), start, limit, accountID) +} + +// CreateOrganizationWithContext creates an organization by +// passing the name of the organization. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-post +func (s *OrganizationService) CreateOrganizationWithContext(ctx context.Context, name string) (*Organization, *Response, error) { + apiEndPoint := "rest/servicedeskapi/organization" + + organization := OrganizationCreationDTO{ + Name: name, + } + + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndPoint, organization) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, nil, err + } + + o := new(Organization) + resp, err := s.client.Do(req, &o) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return o, resp, nil +} + +// CreateOrganization wraps CreateOrganizationWithContext using the background context. +func (s *OrganizationService) CreateOrganization(name string) (*Organization, *Response, error) { + return s.CreateOrganizationWithContext(context.Background(), name) +} + +// GetOrganizationWithContext returns details of an +// organization. Use this method to get organization +// details whenever your application component is +// passed an organization ID but needs to display +// other organization details. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-get +func (s *OrganizationService) GetOrganizationWithContext(ctx context.Context, organizationID int) (*Organization, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d", organizationID) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, nil, err + } + + o := new(Organization) + resp, err := s.client.Do(req, &o) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return o, resp, nil +} + +// GetOrganization wraps GetOrganizationWithContext using the background context. +func (s *OrganizationService) GetOrganization(organizationID int) (*Organization, *Response, error) { + return s.GetOrganizationWithContext(context.Background(), organizationID) +} + +// DeleteOrganizationWithContext deletes an organization. Note that +// the organization is deleted regardless +// of other associations it may have. +// For example, associations with service desks. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-delete +// Caller must close resp.Body +func (s *OrganizationService) DeleteOrganizationWithContext(ctx context.Context, organizationID int) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d", organizationID) + + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, nil) + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// DeleteOrganization wraps DeleteOrganizationWithContext using the background context. +// Caller must close resp.Body +func (s *OrganizationService) DeleteOrganization(organizationID int) (*Response, error) { + return s.DeleteOrganizationWithContext(context.Background(), organizationID) +} + +// GetPropertiesKeysWithContext returns the keys of +// all properties for an organization. Use this resource +// when you need to find out what additional properties +// items have been added to an organization. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-get +func (s *OrganizationService) GetPropertiesKeysWithContext(ctx context.Context, organizationID int) (*PropertyKeys, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property", organizationID) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, nil, err + } + + pk := new(PropertyKeys) + resp, err := s.client.Do(req, &pk) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return pk, resp, nil +} + +// GetPropertiesKeys wraps GetPropertiesKeysWithContext using the background context. +func (s *OrganizationService) GetPropertiesKeys(organizationID int) (*PropertyKeys, *Response, error) { + return s.GetPropertiesKeysWithContext(context.Background(), organizationID) +} + +// GetPropertyWithContext returns the value of a property +// from an organization. Use this method to obtain the JSON +// content for an organization's property. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-propertykey-get +func (s *OrganizationService) GetPropertyWithContext(ctx context.Context, organizationID int, propertyKey string) (*EntityProperty, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property/%s", organizationID, propertyKey) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, nil, err + } + + ep := new(EntityProperty) + resp, err := s.client.Do(req, &ep) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return ep, resp, nil +} + +// GetProperty wraps GetPropertyWithContext using the background context. +func (s *OrganizationService) GetProperty(organizationID int, propertyKey string) (*EntityProperty, *Response, error) { + return s.GetPropertyWithContext(context.Background(), organizationID, propertyKey) +} + +// SetPropertyWithContext sets the value of a +// property for an organization. Use this +// resource to store custom data against an organization. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-propertykey-put +// Caller must close resp.Body +func (s *OrganizationService) SetPropertyWithContext(ctx context.Context, organizationID int, propertyKey string) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property/%s", organizationID, propertyKey) + + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// SetProperty wraps SetPropertyWithContext using the background context. +// Caller must close resp.Body +func (s *OrganizationService) SetProperty(organizationID int, propertyKey string) (*Response, error) { + return s.SetPropertyWithContext(context.Background(), organizationID, propertyKey) +} + +// DeletePropertyWithContext removes a property from an organization. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-property-propertykey-delete +// Caller must close resp.Body +func (s *OrganizationService) DeletePropertyWithContext(ctx context.Context, organizationID int, propertyKey string) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/property/%s", organizationID, propertyKey) + + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// DeleteProperty wraps DeletePropertyWithContext using the background context. +// Caller must close resp.Body +func (s *OrganizationService) DeleteProperty(organizationID int, propertyKey string) (*Response, error) { + return s.DeletePropertyWithContext(context.Background(), organizationID, propertyKey) +} + +// GetUsersWithContext returns all the users +// associated with an organization. Use this +// method where you want to provide a list of +// users for an organization or determine if +// a user is associated with an organization. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-user-get +func (s *OrganizationService) GetUsersWithContext(ctx context.Context, organizationID int, start int, limit int) (*PagedDTO, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/user?start=%d&limit=%d", organizationID, start, limit) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, nil, err + } + + users := new(PagedDTO) + resp, err := s.client.Do(req, &users) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return users, resp, nil +} + +// GetUsers wraps GetUsersWithContext using the background context. +func (s *OrganizationService) GetUsers(organizationID int, start int, limit int) (*PagedDTO, *Response, error) { + return s.GetUsersWithContext(context.Background(), organizationID, start, limit) +} + +// AddUsersWithContext adds users to an organization. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-user-post +// Caller must close resp.Body +func (s *OrganizationService) AddUsersWithContext(ctx context.Context, organizationID int, users OrganizationUsersDTO) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/user", organizationID) + + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndPoint, users) + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// AddUsers wraps AddUsersWithContext using the background context. +// Caller must close resp.Body +func (s *OrganizationService) AddUsers(organizationID int, users OrganizationUsersDTO) (*Response, error) { + return s.AddUsersWithContext(context.Background(), organizationID, users) +} + +// RemoveUsersWithContext removes users from an organization. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-organization-organizationid-user-delete +// Caller must close resp.Body +func (s *OrganizationService) RemoveUsersWithContext(ctx context.Context, organizationID int, users OrganizationUsersDTO) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/organization/%d/user", organizationID) + + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// RemoveUsers wraps RemoveUsersWithContext using the background context. +// Caller must close resp.Body +func (s *OrganizationService) RemoveUsers(organizationID int, users OrganizationUsersDTO) (*Response, error) { + return s.RemoveUsersWithContext(context.Background(), organizationID, users) +} diff --git a/vendor/github.com/andygrunwald/go-jira/permissionscheme.go b/vendor/github.com/andygrunwald/go-jira/permissionscheme.go new file mode 100644 index 0000000000..7af5a8bf89 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/permissionscheme.go @@ -0,0 +1,82 @@ +package jira + +import ( + "context" + "fmt" +) + +// PermissionSchemeService handles permissionschemes for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Permissionscheme +type PermissionSchemeService struct { + client *Client +} +type PermissionSchemes struct { + PermissionSchemes []PermissionScheme `json:"permissionSchemes" structs:"permissionSchemes"` +} + +type Permission struct { + ID int `json:"id" structs:"id"` + Self string `json:"expand" structs:"expand"` + Holder Holder `json:"holder" structs:"holder"` + Name string `json:"permission" structs:"permission"` +} + +type Holder struct { + Type string `json:"type" structs:"type"` + Parameter string `json:"parameter" structs:"parameter"` + Expand string `json:"expand" structs:"expand"` +} + +// GetListWithContext returns a list of all permission schemes +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-get +func (s *PermissionSchemeService) GetListWithContext(ctx context.Context) (*PermissionSchemes, *Response, error) { + apiEndpoint := "/rest/api/3/permissionscheme" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + pss := new(PermissionSchemes) + resp, err := s.client.Do(req, &pss) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return pss, resp, nil +} + +// GetList wraps GetListWithContext using the background context. +func (s *PermissionSchemeService) GetList() (*PermissionSchemes, *Response, error) { + return s.GetListWithContext(context.Background()) +} + +// GetWithContext returns a full representation of the permission scheme for the schemeID +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-permissionscheme-schemeId-get +func (s *PermissionSchemeService) GetWithContext(ctx context.Context, schemeID int) (*PermissionScheme, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/3/permissionscheme/%d", schemeID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + ps := new(PermissionScheme) + resp, err := s.client.Do(req, ps) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + if ps.Self == "" { + return nil, resp, fmt.Errorf("no permissionscheme with ID %d found", schemeID) + } + + return ps, resp, nil +} + +// Get wraps GetWithContext using the background context. +func (s *PermissionSchemeService) Get(schemeID int) (*PermissionScheme, *Response, error) { + return s.GetWithContext(context.Background(), schemeID) +} diff --git a/vendor/github.com/andygrunwald/go-jira/priority.go b/vendor/github.com/andygrunwald/go-jira/priority.go new file mode 100644 index 0000000000..a7b12a4176 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/priority.go @@ -0,0 +1,44 @@ +package jira + +import "context" + +// PriorityService handles priorities for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Priority +type PriorityService struct { + client *Client +} + +// Priority represents a priority of a Jira issue. +// Typical types are "Normal", "Moderate", "Urgent", ... +type Priority struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + IconURL string `json:"iconUrl,omitempty" structs:"iconUrl,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + StatusColor string `json:"statusColor,omitempty" structs:"statusColor,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` +} + +// GetListWithContext gets all priorities from Jira +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-priority-get +func (s *PriorityService) GetListWithContext(ctx context.Context) ([]Priority, *Response, error) { + apiEndpoint := "rest/api/2/priority" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + priorityList := []Priority{} + resp, err := s.client.Do(req, &priorityList) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return priorityList, resp, nil +} + +// GetList wraps GetListWithContext using the background context. +func (s *PriorityService) GetList() ([]Priority, *Response, error) { + return s.GetListWithContext(context.Background()) +} diff --git a/vendor/github.com/andygrunwald/go-jira/project.go b/vendor/github.com/andygrunwald/go-jira/project.go new file mode 100644 index 0000000000..f1000c8138 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/project.go @@ -0,0 +1,182 @@ +package jira + +import ( + "context" + "fmt" + + "github.com/google/go-querystring/query" +) + +// ProjectService handles projects for the Jira instance / API. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project +type ProjectService struct { + client *Client +} + +// ProjectList represent a list of Projects +type ProjectList []struct { + Expand string `json:"expand" structs:"expand"` + Self string `json:"self" structs:"self"` + ID string `json:"id" structs:"id"` + Key string `json:"key" structs:"key"` + Name string `json:"name" structs:"name"` + AvatarUrls AvatarUrls `json:"avatarUrls" structs:"avatarUrls"` + ProjectTypeKey string `json:"projectTypeKey" structs:"projectTypeKey"` + ProjectCategory ProjectCategory `json:"projectCategory,omitempty" structs:"projectsCategory,omitempty"` + IssueTypes []IssueType `json:"issueTypes,omitempty" structs:"issueTypes,omitempty"` +} + +// ProjectCategory represents a single project category +type ProjectCategory struct { + Self string `json:"self" structs:"self,omitempty"` + ID string `json:"id" structs:"id,omitempty"` + Name string `json:"name" structs:"name,omitempty"` + Description string `json:"description" structs:"description,omitempty"` +} + +// Project represents a Jira Project. +type Project struct { + Expand string `json:"expand,omitempty" structs:"expand,omitempty"` + Self string `json:"self,omitempty" structs:"self,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + Key string `json:"key,omitempty" structs:"key,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` + Lead User `json:"lead,omitempty" structs:"lead,omitempty"` + Components []ProjectComponent `json:"components,omitempty" structs:"components,omitempty"` + IssueTypes []IssueType `json:"issueTypes,omitempty" structs:"issueTypes,omitempty"` + URL string `json:"url,omitempty" structs:"url,omitempty"` + Email string `json:"email,omitempty" structs:"email,omitempty"` + AssigneeType string `json:"assigneeType,omitempty" structs:"assigneeType,omitempty"` + Versions []Version `json:"versions,omitempty" structs:"versions,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Roles map[string]string `json:"roles,omitempty" structs:"roles,omitempty"` + AvatarUrls AvatarUrls `json:"avatarUrls,omitempty" structs:"avatarUrls,omitempty"` + ProjectCategory ProjectCategory `json:"projectCategory,omitempty" structs:"projectCategory,omitempty"` +} + +// ProjectComponent represents a single component of a project +type ProjectComponent struct { + Self string `json:"self" structs:"self,omitempty"` + ID string `json:"id" structs:"id,omitempty"` + Name string `json:"name" structs:"name,omitempty"` + Description string `json:"description" structs:"description,omitempty"` + Lead User `json:"lead,omitempty" structs:"lead,omitempty"` + AssigneeType string `json:"assigneeType" structs:"assigneeType,omitempty"` + Assignee User `json:"assignee" structs:"assignee,omitempty"` + RealAssigneeType string `json:"realAssigneeType" structs:"realAssigneeType,omitempty"` + RealAssignee User `json:"realAssignee" structs:"realAssignee,omitempty"` + IsAssigneeTypeValid bool `json:"isAssigneeTypeValid" structs:"isAssigneeTypeValid,omitempty"` + Project string `json:"project" structs:"project,omitempty"` + ProjectID int `json:"projectId" structs:"projectId,omitempty"` +} + +// PermissionScheme represents the permission scheme for the project +type PermissionScheme struct { + Expand string `json:"expand" structs:"expand,omitempty"` + Self string `json:"self" structs:"self,omitempty"` + ID int `json:"id" structs:"id,omitempty"` + Name string `json:"name" structs:"name,omitempty"` + Description string `json:"description" structs:"description,omitempty"` + Permissions []Permission `json:"permissions" structs:"permissions,omitempty"` +} + +// GetListWithContext gets all projects form Jira +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects +func (s *ProjectService) GetListWithContext(ctx context.Context) (*ProjectList, *Response, error) { + return s.ListWithOptionsWithContext(ctx, &GetQueryOptions{}) +} + +// GetList wraps GetListWithContext using the background context. +func (s *ProjectService) GetList() (*ProjectList, *Response, error) { + return s.GetListWithContext(context.Background()) +} + +// ListWithOptionsWithContext gets all projects form Jira with optional query params, like &GetQueryOptions{Expand: "issueTypes"} to get +// a list of all projects and their supported issuetypes +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getAllProjects +func (s *ProjectService) ListWithOptionsWithContext(ctx context.Context, options *GetQueryOptions) (*ProjectList, *Response, error) { + apiEndpoint := "rest/api/2/project" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + if options != nil { + q, err := query.Values(options) + if err != nil { + return nil, nil, err + } + req.URL.RawQuery = q.Encode() + } + + projectList := new(ProjectList) + resp, err := s.client.Do(req, projectList) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return projectList, resp, nil +} + +// ListWithOptions wraps ListWithOptionsWithContext using the background context. +func (s *ProjectService) ListWithOptions(options *GetQueryOptions) (*ProjectList, *Response, error) { + return s.ListWithOptionsWithContext(context.Background(), options) +} + +// GetWithContext returns a full representation of the project for the given issue key. +// Jira will attempt to identify the project by the projectIdOrKey path parameter. +// This can be an project id, or an project key. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject +func (s *ProjectService) GetWithContext(ctx context.Context, projectID string) (*Project, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/project/%s", projectID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + project := new(Project) + resp, err := s.client.Do(req, project) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return project, resp, nil +} + +// Get wraps GetWithContext using the background context. +func (s *ProjectService) Get(projectID string) (*Project, *Response, error) { + return s.GetWithContext(context.Background(), projectID) +} + +// GetPermissionSchemeWithContext returns a full representation of the permission scheme for the project +// Jira will attempt to identify the project by the projectIdOrKey path parameter. +// This can be an project id, or an project key. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/project-getProject +func (s *ProjectService) GetPermissionSchemeWithContext(ctx context.Context, projectID string) (*PermissionScheme, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/project/%s/permissionscheme", projectID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + ps := new(PermissionScheme) + resp, err := s.client.Do(req, ps) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return ps, resp, nil +} + +// GetPermissionScheme wraps GetPermissionSchemeWithContext using the background context. +func (s *ProjectService) GetPermissionScheme(projectID string) (*PermissionScheme, *Response, error) { + return s.GetPermissionSchemeWithContext(context.Background(), projectID) +} diff --git a/vendor/github.com/andygrunwald/go-jira/request.go b/vendor/github.com/andygrunwald/go-jira/request.go new file mode 100644 index 0000000000..a933a57a0a --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/request.go @@ -0,0 +1,123 @@ +package jira + +import ( + "context" + "fmt" +) + +// RequestService handles ServiceDesk customer requests for the Jira instance / API. +type RequestService struct { + client *Client +} + +// Request represents a ServiceDesk customer request. +type Request struct { + IssueID string `json:"issueId,omitempty" structs:"issueId,omitempty"` + IssueKey string `json:"issueKey,omitempty" structs:"issueKey,omitempty"` + TypeID string `json:"requestTypeId,omitempty" structs:"requestTypeId,omitempty"` + ServiceDeskID string `json:"serviceDeskId,omitempty" structs:"serviceDeskId,omitempty"` + Reporter *Customer `json:"reporter,omitempty" structs:"reporter,omitempty"` + FieldValues []RequestFieldValue `json:"requestFieldValues,omitempty" structs:"requestFieldValues,omitempty"` + Status *RequestStatus `json:"currentStatus,omitempty" structs:"currentStatus,omitempty"` + Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"` + Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"` +} + +// RequestFieldValue is a request field. +type RequestFieldValue struct { + FieldID string `json:"fieldId,omitempty" structs:"fieldId,omitempty"` + Label string `json:"label,omitempty" structs:"label,omitempty"` + Value string `json:"value,omitempty" structs:"value,omitempty"` +} + +// RequestDate is the date format used in requests. +type RequestDate struct { + ISO8601 string `json:"iso8601,omitempty" structs:"iso8601,omitempty"` + Jira string `json:"jira,omitempty" structs:"jira,omitempty"` + Friendly string `json:"friendly,omitempty" structs:"friendly,omitempty"` + Epoch int64 `json:"epoch,omitempty" structs:"epoch,omitempty"` +} + +// RequestStatus is the status for a request. +type RequestStatus struct { + Status string + Category string + Date RequestDate +} + +// RequestComment is a comment for a request. +type RequestComment struct { + ID string `json:"id,omitempty" structs:"id,omitempty"` + Body string `json:"body,omitempty" structs:"body,omitempty"` + Public bool `json:"public" structs:"public"` + Author *Customer `json:"author,omitempty" structs:"author,omitempty"` + Created *RequestDate `json:"created,omitempty" structs:"created,omitempty"` + Links *SelfLink `json:"_links,omitempty" structs:"_links,omitempty"` + Expands []string `json:"_expands,omitempty" structs:"_expands,omitempty"` +} + +// CreateWithContext creates a new request. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-request/#api-rest-servicedeskapi-request-post +func (r *RequestService) CreateWithContext(ctx context.Context, requester string, participants []string, request *Request) (*Request, *Response, error) { + apiEndpoint := "rest/servicedeskapi/request" + + payload := struct { + *Request + FieldValues map[string]string `json:"requestFieldValues,omitempty"` + Requester string `json:"raiseOnBehalfOf,omitempty"` + Participants []string `json:"requestParticipants,omitempty"` + }{ + Request: request, + FieldValues: make(map[string]string), + Requester: requester, + Participants: participants, + } + + for _, field := range request.FieldValues { + payload.FieldValues[field.FieldID] = field.Value + } + + req, err := r.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload) + if err != nil { + return nil, nil, err + } + + responseRequest := new(Request) + resp, err := r.client.Do(req, responseRequest) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + + return responseRequest, resp, nil +} + +// Create wraps CreateWithContext using the background context. +func (r *RequestService) Create(requester string, participants []string, request *Request) (*Request, *Response, error) { + return r.CreateWithContext(context.Background(), requester, participants, request) +} + +// CreateCommentWithContext creates a comment on a request. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-request/#api-rest-servicedeskapi-request-issueidorkey-comment-post +func (r *RequestService) CreateCommentWithContext(ctx context.Context, issueIDOrKey string, comment *RequestComment) (*RequestComment, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/servicedeskapi/request/%v/comment", issueIDOrKey) + + req, err := r.client.NewRequestWithContext(ctx, "POST", apiEndpoint, comment) + if err != nil { + return nil, nil, err + } + + responseComment := new(RequestComment) + resp, err := r.client.Do(req, responseComment) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + + return responseComment, resp, nil +} + +// CreateComment wraps CreateCommentWithContext using the background context. +func (r *RequestService) CreateComment(issueIDOrKey string, comment *RequestComment) (*RequestComment, *Response, error) { + return r.CreateCommentWithContext(context.Background(), issueIDOrKey, comment) +} diff --git a/vendor/github.com/andygrunwald/go-jira/request_context.go b/vendor/github.com/andygrunwald/go-jira/request_context.go new file mode 100644 index 0000000000..9f3e26475d --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/request_context.go @@ -0,0 +1,24 @@ +//go:build go1.13 +// +build go1.13 + +// This file provides glue to use Context in `http.Request` with +// Go version 1.13 and higher. + +// The function `http.NewRequestWithContext` has been added in Go 1.13. +// Before the release 1.13, to use Context we need creat `http.Request` +// then use the method `WithContext` to create a new `http.Request` +// with Context from the existing `http.Request`. +// +// Doc: https://golang.org/doc/go1.13#net/http + +package jira + +import ( + "context" + "io" + "net/http" +) + +func newRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) { + return http.NewRequestWithContext(ctx, method, url, body) +} diff --git a/vendor/github.com/andygrunwald/go-jira/request_legacy.go b/vendor/github.com/andygrunwald/go-jira/request_legacy.go new file mode 100644 index 0000000000..93eb65e8a4 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/request_legacy.go @@ -0,0 +1,29 @@ +//go:build !go1.13 +// +build !go1.13 + +// This file provides glue to use Context in `http.Request` with +// Go version before 1.13. + +// The function `http.NewRequestWithContext` has been added in Go 1.13. +// Before the release 1.13, to use Context we need creat `http.Request` +// then use the method `WithContext` to create a new `http.Request` +// with Context from the existing `http.Request`. +// +// Doc: https://golang.org/doc/go1.13#net/http + +package jira + +import ( + "context" + "io" + "net/http" +) + +func newRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*http.Request, error) { + r, err := http.NewRequest(method, url, body) + if err != nil { + return nil, err + } + + return r.WithContext(ctx), nil +} diff --git a/vendor/github.com/andygrunwald/go-jira/resolution.go b/vendor/github.com/andygrunwald/go-jira/resolution.go new file mode 100644 index 0000000000..e23d5650fb --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/resolution.go @@ -0,0 +1,42 @@ +package jira + +import "context" + +// ResolutionService handles resolutions for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Resolution +type ResolutionService struct { + client *Client +} + +// Resolution represents a resolution of a Jira issue. +// Typical types are "Fixed", "Suspended", "Won't Fix", ... +type Resolution struct { + Self string `json:"self" structs:"self"` + ID string `json:"id" structs:"id"` + Description string `json:"description" structs:"description"` + Name string `json:"name" structs:"name"` +} + +// GetListWithContext gets all resolutions from Jira +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-resolution-get +func (s *ResolutionService) GetListWithContext(ctx context.Context) ([]Resolution, *Response, error) { + apiEndpoint := "rest/api/2/resolution" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + resolutionList := []Resolution{} + resp, err := s.client.Do(req, &resolutionList) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return resolutionList, resp, nil +} + +// GetList wraps GetListWithContext using the background context. +func (s *ResolutionService) GetList() ([]Resolution, *Response, error) { + return s.GetListWithContext(context.Background()) +} diff --git a/vendor/github.com/andygrunwald/go-jira/role.go b/vendor/github.com/andygrunwald/go-jira/role.go new file mode 100644 index 0000000000..66d223ff4a --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/role.go @@ -0,0 +1,87 @@ +package jira + +import ( + "context" + "fmt" +) + +// RoleService handles roles for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Role +type RoleService struct { + client *Client +} + +// Role represents a Jira product role +type Role struct { + Self string `json:"self" structs:"self"` + Name string `json:"name" structs:"name"` + ID int `json:"id" structs:"id"` + Description string `json:"description" structs:"description"` + Actors []*Actor `json:"actors" structs:"actors"` +} + +// Actor represents a Jira actor +type Actor struct { + ID int `json:"id" structs:"id"` + DisplayName string `json:"displayName" structs:"displayName"` + Type string `json:"type" structs:"type"` + Name string `json:"name" structs:"name"` + AvatarURL string `json:"avatarUrl" structs:"avatarUrl"` + ActorUser *ActorUser `json:"actorUser" structs:"actoruser"` +} + +// ActorUser contains the account id of the actor/user +type ActorUser struct { + AccountID string `json:"accountId" structs:"accountId"` +} + +// GetListWithContext returns a list of all available project roles +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-get +func (s *RoleService) GetListWithContext(ctx context.Context) (*[]Role, *Response, error) { + apiEndpoint := "rest/api/3/role" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + roles := new([]Role) + resp, err := s.client.Do(req, roles) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + return roles, resp, err +} + +// GetList wraps GetListWithContext using the background context. +func (s *RoleService) GetList() (*[]Role, *Response, error) { + return s.GetListWithContext(context.Background()) +} + +// GetWithContext retreives a single Role from Jira +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-api-3-role-id-get +func (s *RoleService) GetWithContext(ctx context.Context, roleID int) (*Role, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/3/role/%d", roleID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + role := new(Role) + resp, err := s.client.Do(req, role) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + if role.Self == "" { + return nil, resp, fmt.Errorf("no role with ID %d found", roleID) + } + + return role, resp, err +} + +// Get wraps GetWithContext using the background context. +func (s *RoleService) Get(roleID int) (*Role, *Response, error) { + return s.GetWithContext(context.Background(), roleID) +} diff --git a/vendor/github.com/andygrunwald/go-jira/servicedesk.go b/vendor/github.com/andygrunwald/go-jira/servicedesk.go new file mode 100644 index 0000000000..7fbffc0b71 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/servicedesk.go @@ -0,0 +1,227 @@ +package jira + +import ( + "context" + "encoding/json" + "fmt" + "io" + "io/ioutil" + + "github.com/google/go-querystring/query" +) + +// ServiceDeskService handles ServiceDesk for the Jira instance / API. +type ServiceDeskService struct { + client *Client +} + +// ServiceDeskOrganizationDTO is a DTO for ServiceDesk organizations +type ServiceDeskOrganizationDTO struct { + OrganizationID int `json:"organizationId,omitempty" structs:"organizationId,omitempty"` +} + +// GetOrganizationsWithContext returns a list of +// all organizations associated with a service desk. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-get +func (s *ServiceDeskService) GetOrganizationsWithContext(ctx context.Context, serviceDeskID interface{}, start int, limit int, accountID string) (*PagedDTO, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization?start=%d&limit=%d", serviceDeskID, start, limit) + if accountID != "" { + apiEndPoint += fmt.Sprintf("&accountId=%s", accountID) + } + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + if err != nil { + return nil, nil, err + } + + orgs := new(PagedDTO) + resp, err := s.client.Do(req, &orgs) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return orgs, resp, nil +} + +// GetOrganizations wraps GetOrganizationsWithContext using the background context. +func (s *ServiceDeskService) GetOrganizations(serviceDeskID interface{}, start int, limit int, accountID string) (*PagedDTO, *Response, error) { + return s.GetOrganizationsWithContext(context.Background(), serviceDeskID, start, limit, accountID) +} + +// AddOrganizationWithContext adds an organization to +// a service desk. If the organization ID is already +// associated with the service desk, no change is made +// and the resource returns a 204 success code. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-post +// Caller must close resp.Body +func (s *ServiceDeskService) AddOrganizationWithContext(ctx context.Context, serviceDeskID interface{}, organizationID int) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization", serviceDeskID) + + organization := ServiceDeskOrganizationDTO{ + OrganizationID: organizationID, + } + + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndPoint, organization) + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// AddOrganization wraps AddOrganizationWithContext using the background context. +// Caller must close resp.Body +func (s *ServiceDeskService) AddOrganization(serviceDeskID interface{}, organizationID int) (*Response, error) { + return s.AddOrganizationWithContext(context.Background(), serviceDeskID, organizationID) +} + +// RemoveOrganizationWithContext removes an organization +// from a service desk. If the organization ID does not +// match an organization associated with the service desk, +// no change is made and the resource returns a 204 success code. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-organization/#api-rest-servicedeskapi-servicedesk-servicedeskid-organization-delete +// Caller must close resp.Body +func (s *ServiceDeskService) RemoveOrganizationWithContext(ctx context.Context, serviceDeskID interface{}, organizationID int) (*Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/organization", serviceDeskID) + + organization := ServiceDeskOrganizationDTO{ + OrganizationID: organizationID, + } + + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndPoint, organization) + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return resp, jerr + } + + return resp, nil +} + +// RemoveOrganization wraps RemoveOrganizationWithContext using the background context. +// Caller must close resp.Body +func (s *ServiceDeskService) RemoveOrganization(serviceDeskID interface{}, organizationID int) (*Response, error) { + return s.RemoveOrganizationWithContext(context.Background(), serviceDeskID, organizationID) +} + +// AddCustomersWithContext adds customers to the given service desk. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-servicedesk/#api-rest-servicedeskapi-servicedesk-servicedeskid-customer-post +func (s *ServiceDeskService) AddCustomersWithContext(ctx context.Context, serviceDeskID interface{}, acountIDs ...string) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/customer", serviceDeskID) + + payload := struct { + AccountIDs []string `json:"accountIds"` + }{ + AccountIDs: acountIDs, + } + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return resp, NewJiraError(resp, err) + } + + defer resp.Body.Close() + _, _ = io.Copy(ioutil.Discard, resp.Body) + + return resp, nil +} + +// AddCustomers wraps AddCustomersWithContext using the background context. +func (s *ServiceDeskService) AddCustomers(serviceDeskID interface{}, acountIDs ...string) (*Response, error) { + return s.AddCustomersWithContext(context.Background(), serviceDeskID, acountIDs...) +} + +// RemoveCustomersWithContext removes customers to the given service desk. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-servicedesk/#api-rest-servicedeskapi-servicedesk-servicedeskid-customer-delete +func (s *ServiceDeskService) RemoveCustomersWithContext(ctx context.Context, serviceDeskID interface{}, acountIDs ...string) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/customer", serviceDeskID) + + payload := struct { + AccountIDs []string `json:"accountIDs"` + }{ + AccountIDs: acountIDs, + } + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, payload) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return resp, NewJiraError(resp, err) + } + + defer resp.Body.Close() + _, _ = io.Copy(ioutil.Discard, resp.Body) + + return resp, nil +} + +// RemoveCustomers wraps RemoveCustomersWithContext using the background context. +func (s *ServiceDeskService) RemoveCustomers(serviceDeskID interface{}, acountIDs ...string) (*Response, error) { + return s.RemoveCustomersWithContext(context.Background(), serviceDeskID, acountIDs...) +} + +// ListCustomersWithContext lists customers for a ServiceDesk. +// +// https://developer.atlassian.com/cloud/jira/service-desk/rest/api-group-servicedesk/#api-rest-servicedeskapi-servicedesk-servicedeskid-customer-get +func (s *ServiceDeskService) ListCustomersWithContext(ctx context.Context, serviceDeskID interface{}, options *CustomerListOptions) (*CustomerList, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/servicedeskapi/servicedesk/%v/customer", serviceDeskID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + // this is an experiemntal endpoint + req.Header.Set("X-ExperimentalApi", "opt-in") + + if options != nil { + q, err := query.Values(options) + if err != nil { + return nil, nil, err + } + req.URL.RawQuery = q.Encode() + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + defer resp.Body.Close() + + customerList := new(CustomerList) + if err := json.NewDecoder(resp.Body).Decode(customerList); err != nil { + return nil, resp, fmt.Errorf("could not unmarshall the data into struct") + } + + return customerList, resp, nil +} + +// ListCustomers wraps ListCustomersWithContext using the background context. +func (s *ServiceDeskService) ListCustomers(serviceDeskID interface{}, options *CustomerListOptions) (*CustomerList, *Response, error) { + return s.ListCustomersWithContext(context.Background(), serviceDeskID, options) +} diff --git a/vendor/github.com/andygrunwald/go-jira/sprint.go b/vendor/github.com/andygrunwald/go-jira/sprint.go new file mode 100644 index 0000000000..f0f98d6f4f --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/sprint.go @@ -0,0 +1,125 @@ +package jira + +import ( + "context" + "fmt" + + "github.com/google/go-querystring/query" +) + +// SprintService handles sprints in Jira Agile API. +// See https://docs.atlassian.com/jira-software/REST/cloud/ +type SprintService struct { + client *Client +} + +// IssuesWrapper represents a wrapper struct for moving issues to sprint +type IssuesWrapper struct { + Issues []string `json:"issues"` +} + +// IssuesInSprintResult represents a wrapper struct for search result +type IssuesInSprintResult struct { + Issues []Issue `json:"issues"` +} + +// MoveIssuesToSprintWithContext moves issues to a sprint, for a given sprint Id. +// Issues can only be moved to open or active sprints. +// The maximum number of issues that can be moved in one operation is 50. +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-moveIssuesToSprint +// Caller must close resp.Body +func (s *SprintService) MoveIssuesToSprintWithContext(ctx context.Context, sprintID int, issueIDs []string) (*Response, error) { + apiEndpoint := fmt.Sprintf("rest/agile/1.0/sprint/%d/issue", sprintID) + + payload := IssuesWrapper{Issues: issueIDs} + + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, payload) + + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + err = NewJiraError(resp, err) + } + return resp, err +} + +// MoveIssuesToSprint wraps MoveIssuesToSprintWithContext using the background context. +// Caller must close resp.Body +func (s *SprintService) MoveIssuesToSprint(sprintID int, issueIDs []string) (*Response, error) { + return s.MoveIssuesToSprintWithContext(context.Background(), sprintID, issueIDs) +} + +// GetIssuesForSprintWithContext returns all issues in a sprint, for a given sprint Id. +// This only includes issues that the user has permission to view. +// By default, the returned issues are ordered by rank. +// +// Jira API Docs: https://docs.atlassian.com/jira-software/REST/cloud/#agile/1.0/sprint-getIssuesForSprint +func (s *SprintService) GetIssuesForSprintWithContext(ctx context.Context, sprintID int) ([]Issue, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/agile/1.0/sprint/%d/issue", sprintID) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + + if err != nil { + return nil, nil, err + } + + result := new(IssuesInSprintResult) + resp, err := s.client.Do(req, result) + if err != nil { + err = NewJiraError(resp, err) + } + + return result.Issues, resp, err +} + +// GetIssuesForSprint wraps GetIssuesForSprintWithContext using the background context. +func (s *SprintService) GetIssuesForSprint(sprintID int) ([]Issue, *Response, error) { + return s.GetIssuesForSprintWithContext(context.Background(), sprintID) +} + +// GetIssueWithContext returns a full representation of the issue for the given issue key. +// Jira will attempt to identify the issue by the issueIdOrKey path parameter. +// This can be an issue id, or an issue key. +// If the issue cannot be found via an exact match, Jira will also look for the issue in a case-insensitive way, or by looking to see if the issue was moved. +// +// The given options will be appended to the query string +// +// Jira API docs: https://docs.atlassian.com/jira-software/REST/7.3.1/#agile/1.0/issue-getIssue +// +// TODO: create agile service for holding all agile apis' implementation +func (s *SprintService) GetIssueWithContext(ctx context.Context, issueID string, options *GetQueryOptions) (*Issue, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/agile/1.0/issue/%s", issueID) + + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + + if err != nil { + return nil, nil, err + } + + if options != nil { + q, err := query.Values(options) + if err != nil { + return nil, nil, err + } + req.URL.RawQuery = q.Encode() + } + + issue := new(Issue) + resp, err := s.client.Do(req, issue) + + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return issue, resp, nil +} + +// GetIssue wraps GetIssueWithContext using the background context. +func (s *SprintService) GetIssue(issueID string, options *GetQueryOptions) (*Issue, *Response, error) { + return s.GetIssueWithContext(context.Background(), issueID, options) +} diff --git a/vendor/github.com/andygrunwald/go-jira/status.go b/vendor/github.com/andygrunwald/go-jira/status.go new file mode 100644 index 0000000000..a37039296c --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/status.go @@ -0,0 +1,47 @@ +package jira + +import "context" + +// StatusService handles staties for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Workflow-statuses +type StatusService struct { + client *Client +} + +// Status represents the current status of a Jira issue. +// Typical status are "Open", "In Progress", "Closed", ... +// Status can be user defined in every Jira instance. +type Status struct { + Self string `json:"self" structs:"self"` + Description string `json:"description" structs:"description"` + IconURL string `json:"iconUrl" structs:"iconUrl"` + Name string `json:"name" structs:"name"` + ID string `json:"id" structs:"id"` + StatusCategory StatusCategory `json:"statusCategory" structs:"statusCategory"` +} + +// GetAllStatusesWithContext returns a list of all statuses associated with workflows. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-status-get +func (s *StatusService) GetAllStatusesWithContext(ctx context.Context) ([]Status, *Response, error) { + apiEndpoint := "rest/api/2/status" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + + if err != nil { + return nil, nil, err + } + + statusList := []Status{} + resp, err := s.client.Do(req, &statusList) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + + return statusList, resp, nil +} + +// GetAllStatuses wraps GetAllStatusesWithContext using the background context. +func (s *StatusService) GetAllStatuses() ([]Status, *Response, error) { + return s.GetAllStatusesWithContext(context.Background()) +} diff --git a/vendor/github.com/andygrunwald/go-jira/statuscategory.go b/vendor/github.com/andygrunwald/go-jira/statuscategory.go new file mode 100644 index 0000000000..bed5c566ca --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/statuscategory.go @@ -0,0 +1,51 @@ +package jira + +import "context" + +// StatusCategoryService handles status categories for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-Statuscategory +type StatusCategoryService struct { + client *Client +} + +// StatusCategory represents the category a status belongs to. +// Those categories can be user defined in every Jira instance. +type StatusCategory struct { + Self string `json:"self" structs:"self"` + ID int `json:"id" structs:"id"` + Name string `json:"name" structs:"name"` + Key string `json:"key" structs:"key"` + ColorName string `json:"colorName" structs:"colorName"` +} + +// These constants are the keys of the default Jira status categories +const ( + StatusCategoryComplete = "done" + StatusCategoryInProgress = "indeterminate" + StatusCategoryToDo = "new" + StatusCategoryUndefined = "undefined" +) + +// GetListWithContext gets all status categories from Jira +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-statuscategory-get +func (s *StatusCategoryService) GetListWithContext(ctx context.Context) ([]StatusCategory, *Response, error) { + apiEndpoint := "rest/api/2/statuscategory" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + statusCategoryList := []StatusCategory{} + resp, err := s.client.Do(req, &statusCategoryList) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return statusCategoryList, resp, nil +} + +// GetList wraps GetListWithContext using the background context. +func (s *StatusCategoryService) GetList() ([]StatusCategory, *Response, error) { + return s.GetListWithContext(context.Background()) +} diff --git a/vendor/github.com/andygrunwald/go-jira/types.go b/vendor/github.com/andygrunwald/go-jira/types.go new file mode 100644 index 0000000000..b99fc1c3fe --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/types.go @@ -0,0 +1,9 @@ +package jira + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { + p := new(bool) + *p = v + return p +} diff --git a/vendor/github.com/andygrunwald/go-jira/user.go b/vendor/github.com/andygrunwald/go-jira/user.go new file mode 100644 index 0000000000..78d603967f --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/user.go @@ -0,0 +1,294 @@ +package jira + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" +) + +// UserService handles users for the Jira instance / API. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-group-Users +type UserService struct { + client *Client +} + +// User represents a Jira user. +type User struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + AccountID string `json:"accountId,omitempty" structs:"accountId,omitempty"` + AccountType string `json:"accountType,omitempty" structs:"accountType,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Key string `json:"key,omitempty" structs:"key,omitempty"` + Password string `json:"-"` + EmailAddress string `json:"emailAddress,omitempty" structs:"emailAddress,omitempty"` + AvatarUrls AvatarUrls `json:"avatarUrls,omitempty" structs:"avatarUrls,omitempty"` + DisplayName string `json:"displayName,omitempty" structs:"displayName,omitempty"` + Active bool `json:"active,omitempty" structs:"active,omitempty"` + TimeZone string `json:"timeZone,omitempty" structs:"timeZone,omitempty"` + Locale string `json:"locale,omitempty" structs:"locale,omitempty"` + ApplicationKeys []string `json:"applicationKeys,omitempty" structs:"applicationKeys,omitempty"` +} + +// UserGroup represents the group list +type UserGroup struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` +} + +type userSearchParam struct { + name string + value string +} + +type userSearch []userSearchParam + +type userSearchF func(userSearch) userSearch + +// GetWithContext gets user info from Jira using its Account Id +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-get +func (s *UserService) GetWithContext(ctx context.Context, accountId string) (*User, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountId) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + user := new(User) + resp, err := s.client.Do(req, user) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return user, resp, nil +} + +// Get wraps GetWithContext using the background context. +func (s *UserService) Get(accountId string) (*User, *Response, error) { + return s.GetWithContext(context.Background(), accountId) +} + +// GetByAccountIDWithContext gets user info from Jira +// Searching by another parameter that is not accountId is deprecated, +// but this method is kept for backwards compatibility +// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-getUser +func (s *UserService) GetByAccountIDWithContext(ctx context.Context, accountID string) (*User, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + user := new(User) + resp, err := s.client.Do(req, user) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return user, resp, nil +} + +// GetByAccountID wraps GetByAccountIDWithContext using the background context. +func (s *UserService) GetByAccountID(accountID string) (*User, *Response, error) { + return s.GetByAccountIDWithContext(context.Background(), accountID) +} + +// CreateWithContext creates an user in Jira. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/cloud/#api/2/user-createUser +func (s *UserService) CreateWithContext(ctx context.Context, user *User) (*User, *Response, error) { + apiEndpoint := "/rest/api/2/user" + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, user) + if err != nil { + return nil, nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return nil, resp, err + } + + responseUser := new(User) + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + e := fmt.Errorf("could not read the returned data") + return nil, resp, NewJiraError(resp, e) + } + err = json.Unmarshal(data, responseUser) + if err != nil { + e := fmt.Errorf("could not unmarshall the data into struct") + return nil, resp, NewJiraError(resp, e) + } + return responseUser, resp, nil +} + +// Create wraps CreateWithContext using the background context. +func (s *UserService) Create(user *User) (*User, *Response, error) { + return s.CreateWithContext(context.Background(), user) +} + +// DeleteWithContext deletes an user from Jira. +// Returns http.StatusNoContent on success. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-delete +// Caller must close resp.Body +func (s *UserService) DeleteWithContext(ctx context.Context, accountId string) (*Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/user?accountId=%s", accountId) + req, err := s.client.NewRequestWithContext(ctx, "DELETE", apiEndpoint, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return resp, NewJiraError(resp, err) + } + return resp, nil +} + +// Delete wraps DeleteWithContext using the background context. +// Caller must close resp.Body +func (s *UserService) Delete(accountId string) (*Response, error) { + return s.DeleteWithContext(context.Background(), accountId) +} + +// GetGroupsWithContext returns the groups which the user belongs to +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-groups-get +func (s *UserService) GetGroupsWithContext(ctx context.Context, accountId string) (*[]UserGroup, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/user/groups?accountId=%s", accountId) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + userGroups := new([]UserGroup) + resp, err := s.client.Do(req, userGroups) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return userGroups, resp, nil +} + +// GetGroups wraps GetGroupsWithContext using the background context. +func (s *UserService) GetGroups(accountId string) (*[]UserGroup, *Response, error) { + return s.GetGroupsWithContext(context.Background(), accountId) +} + +// GetSelfWithContext information about the current logged-in user +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-myself-get +func (s *UserService) GetSelfWithContext(ctx context.Context) (*User, *Response, error) { + const apiEndpoint = "rest/api/2/myself" + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + var user User + resp, err := s.client.Do(req, &user) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return &user, resp, nil +} + +// GetSelf wraps GetSelfWithContext using the background context. +func (s *UserService) GetSelf() (*User, *Response, error) { + return s.GetSelfWithContext(context.Background()) +} + +// WithMaxResults sets the max results to return +func WithMaxResults(maxResults int) userSearchF { + return func(s userSearch) userSearch { + s = append(s, userSearchParam{name: "maxResults", value: fmt.Sprintf("%d", maxResults)}) + return s + } +} + +// WithStartAt set the start pager +func WithStartAt(startAt int) userSearchF { + return func(s userSearch) userSearch { + s = append(s, userSearchParam{name: "startAt", value: fmt.Sprintf("%d", startAt)}) + return s + } +} + +// WithActive sets the active users lookup +func WithActive(active bool) userSearchF { + return func(s userSearch) userSearch { + s = append(s, userSearchParam{name: "includeActive", value: fmt.Sprintf("%t", active)}) + return s + } +} + +// WithInactive sets the inactive users lookup +func WithInactive(inactive bool) userSearchF { + return func(s userSearch) userSearch { + s = append(s, userSearchParam{name: "includeInactive", value: fmt.Sprintf("%t", inactive)}) + return s + } +} + +// WithUsername sets the username to search +func WithUsername(username string) userSearchF { + return func(s userSearch) userSearch { + s = append(s, userSearchParam{name: "username", value: username}) + return s + } +} + +// WithAccountId sets the account id to search +func WithAccountId(accountId string) userSearchF { + return func(s userSearch) userSearch { + s = append(s, userSearchParam{name: "accountId", value: accountId}) + return s + } +} + +// WithProperty sets the property (Property keys are specified by path) to search +func WithProperty(property string) userSearchF { + return func(s userSearch) userSearch { + s = append(s, userSearchParam{name: "property", value: property}) + return s + } +} + +// FindWithContext searches for user info from Jira: +// It can find users by email or display name using the query parameter +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v2/#api-rest-api-2-user-search-get +func (s *UserService) FindWithContext(ctx context.Context, property string, tweaks ...userSearchF) ([]User, *Response, error) { + search := []userSearchParam{ + { + name: "query", + value: property, + }, + } + for _, f := range tweaks { + search = f(search) + } + + var queryString = "" + for _, param := range search { + queryString += param.name + "=" + param.value + "&" + } + + apiEndpoint := fmt.Sprintf("/rest/api/2/user/search?%s", queryString[:len(queryString)-1]) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + users := []User{} + resp, err := s.client.Do(req, &users) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return users, resp, nil +} + +// Find wraps FindWithContext using the background context. +func (s *UserService) Find(property string, tweaks ...userSearchF) ([]User, *Response, error) { + return s.FindWithContext(context.Background(), property, tweaks...) +} diff --git a/vendor/github.com/andygrunwald/go-jira/version.go b/vendor/github.com/andygrunwald/go-jira/version.go new file mode 100644 index 0000000000..bca12a4534 --- /dev/null +++ b/vendor/github.com/andygrunwald/go-jira/version.go @@ -0,0 +1,115 @@ +package jira + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" +) + +// VersionService handles Versions for the Jira instance / API. +// +// Jira API docs: https://docs.atlassian.com/jira/REST/latest/#api/2/version +type VersionService struct { + client *Client +} + +// Version represents a single release version of a project +type Version struct { + Self string `json:"self,omitempty" structs:"self,omitempty"` + ID string `json:"id,omitempty" structs:"id,omitempty"` + Name string `json:"name,omitempty" structs:"name,omitempty"` + Description string `json:"description,omitempty" structs:"description,omitempty"` + Archived *bool `json:"archived,omitempty" structs:"archived,omitempty"` + Released *bool `json:"released,omitempty" structs:"released,omitempty"` + ReleaseDate string `json:"releaseDate,omitempty" structs:"releaseDate,omitempty"` + UserReleaseDate string `json:"userReleaseDate,omitempty" structs:"userReleaseDate,omitempty"` + ProjectID int `json:"projectId,omitempty" structs:"projectId,omitempty"` // Unlike other IDs, this is returned as a number + StartDate string `json:"startDate,omitempty" structs:"startDate,omitempty"` +} + +// GetWithContext gets version info from Jira +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-get +func (s *VersionService) GetWithContext(ctx context.Context, versionID int) (*Version, *Response, error) { + apiEndpoint := fmt.Sprintf("/rest/api/2/version/%v", versionID) + req, err := s.client.NewRequestWithContext(ctx, "GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + version := new(Version) + resp, err := s.client.Do(req, version) + if err != nil { + return nil, resp, NewJiraError(resp, err) + } + return version, resp, nil +} + +// Get wraps GetWithContext using the background context. +func (s *VersionService) Get(versionID int) (*Version, *Response, error) { + return s.GetWithContext(context.Background(), versionID) +} + +// CreateWithContext creates a version in Jira. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-post +func (s *VersionService) CreateWithContext(ctx context.Context, version *Version) (*Version, *Response, error) { + apiEndpoint := "/rest/api/2/version" + req, err := s.client.NewRequestWithContext(ctx, "POST", apiEndpoint, version) + if err != nil { + return nil, nil, err + } + + resp, err := s.client.Do(req, nil) + if err != nil { + return nil, resp, err + } + + responseVersion := new(Version) + defer resp.Body.Close() + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + e := fmt.Errorf("could not read the returned data") + return nil, resp, NewJiraError(resp, e) + } + err = json.Unmarshal(data, responseVersion) + if err != nil { + e := fmt.Errorf("could not unmarshall the data into struct") + return nil, resp, NewJiraError(resp, e) + } + return responseVersion, resp, nil +} + +// Create wraps CreateWithContext using the background context. +func (s *VersionService) Create(version *Version) (*Version, *Response, error) { + return s.CreateWithContext(context.Background(), version) +} + +// UpdateWithContext updates a version from a JSON representation. +// +// Jira API docs: https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-version-id-put +// Caller must close resp.Body +func (s *VersionService) UpdateWithContext(ctx context.Context, version *Version) (*Version, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/version/%v", version.ID) + req, err := s.client.NewRequestWithContext(ctx, "PUT", apiEndpoint, version) + if err != nil { + return nil, nil, err + } + resp, err := s.client.Do(req, nil) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + // This is just to follow the rest of the API's convention of returning a version. + // Returning the same pointer here is pointless, so we return a copy instead. + ret := *version + return &ret, resp, nil +} + +// Update wraps UpdateWithContext using the background context. +// Caller must close resp.Body +func (s *VersionService) Update(version *Version) (*Version, *Response, error) { + return s.UpdateWithContext(context.Background(), version) +} diff --git a/vendor/github.com/fatih/structs/.gitignore b/vendor/github.com/fatih/structs/.gitignore new file mode 100644 index 0000000000..836562412f --- /dev/null +++ b/vendor/github.com/fatih/structs/.gitignore @@ -0,0 +1,23 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test diff --git a/vendor/github.com/fatih/structs/.travis.yml b/vendor/github.com/fatih/structs/.travis.yml new file mode 100644 index 0000000000..a08df79812 --- /dev/null +++ b/vendor/github.com/fatih/structs/.travis.yml @@ -0,0 +1,13 @@ +language: go +go: + - 1.7.x + - 1.8.x + - 1.9.x + - tip +sudo: false +before_install: +- go get github.com/axw/gocov/gocov +- go get github.com/mattn/goveralls +- if ! go get github.com/golang/tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi +script: +- $HOME/gopath/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/fatih/structs/LICENSE b/vendor/github.com/fatih/structs/LICENSE new file mode 100644 index 0000000000..34504e4b3e --- /dev/null +++ b/vendor/github.com/fatih/structs/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Fatih Arslan + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/github.com/fatih/structs/README.md b/vendor/github.com/fatih/structs/README.md new file mode 100644 index 0000000000..a75eabf37b --- /dev/null +++ b/vendor/github.com/fatih/structs/README.md @@ -0,0 +1,163 @@ +# Structs [![GoDoc](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](http://godoc.org/github.com/fatih/structs) [![Build Status](http://img.shields.io/travis/fatih/structs.svg?style=flat-square)](https://travis-ci.org/fatih/structs) [![Coverage Status](http://img.shields.io/coveralls/fatih/structs.svg?style=flat-square)](https://coveralls.io/r/fatih/structs) + +Structs contains various utilities to work with Go (Golang) structs. It was +initially used by me to convert a struct into a `map[string]interface{}`. With +time I've added other utilities for structs. It's basically a high level +package based on primitives from the reflect package. Feel free to add new +functions or improve the existing code. + +## Install + +```bash +go get github.com/fatih/structs +``` + +## Usage and Examples + +Just like the standard lib `strings`, `bytes` and co packages, `structs` has +many global functions to manipulate or organize your struct data. Lets define +and declare a struct: + +```go +type Server struct { + Name string `json:"name,omitempty"` + ID int + Enabled bool + users []string // not exported + http.Server // embedded +} + +server := &Server{ + Name: "gopher", + ID: 123456, + Enabled: true, +} +``` + +```go +// Convert a struct to a map[string]interface{} +// => {"Name":"gopher", "ID":123456, "Enabled":true} +m := structs.Map(server) + +// Convert the values of a struct to a []interface{} +// => ["gopher", 123456, true] +v := structs.Values(server) + +// Convert the names of a struct to a []string +// (see "Names methods" for more info about fields) +n := structs.Names(server) + +// Convert the values of a struct to a []*Field +// (see "Field methods" for more info about fields) +f := structs.Fields(server) + +// Return the struct name => "Server" +n := structs.Name(server) + +// Check if any field of a struct is initialized or not. +h := structs.HasZero(server) + +// Check if all fields of a struct is initialized or not. +z := structs.IsZero(server) + +// Check if server is a struct or a pointer to struct +i := structs.IsStruct(server) +``` + +### Struct methods + +The structs functions can be also used as independent methods by creating a new +`*structs.Struct`. This is handy if you want to have more control over the +structs (such as retrieving a single Field). + +```go +// Create a new struct type: +s := structs.New(server) + +m := s.Map() // Get a map[string]interface{} +v := s.Values() // Get a []interface{} +f := s.Fields() // Get a []*Field +n := s.Names() // Get a []string +f := s.Field(name) // Get a *Field based on the given field name +f, ok := s.FieldOk(name) // Get a *Field based on the given field name +n := s.Name() // Get the struct name +h := s.HasZero() // Check if any field is uninitialized +z := s.IsZero() // Check if all fields are uninitialized +``` + +### Field methods + +We can easily examine a single Field for more detail. Below you can see how we +get and interact with various field methods: + + +```go +s := structs.New(server) + +// Get the Field struct for the "Name" field +name := s.Field("Name") + +// Get the underlying value, value => "gopher" +value := name.Value().(string) + +// Set the field's value +name.Set("another gopher") + +// Get the field's kind, kind => "string" +name.Kind() + +// Check if the field is exported or not +if name.IsExported() { + fmt.Println("Name field is exported") +} + +// Check if the value is a zero value, such as "" for string, 0 for int +if !name.IsZero() { + fmt.Println("Name is initialized") +} + +// Check if the field is an anonymous (embedded) field +if !name.IsEmbedded() { + fmt.Println("Name is not an embedded field") +} + +// Get the Field's tag value for tag name "json", tag value => "name,omitempty" +tagValue := name.Tag("json") +``` + +Nested structs are supported too: + +```go +addrField := s.Field("Server").Field("Addr") + +// Get the value for addr +a := addrField.Value().(string) + +// Or get all fields +httpServer := s.Field("Server").Fields() +``` + +We can also get a slice of Fields from the Struct type to iterate over all +fields. This is handy if you wish to examine all fields: + +```go +s := structs.New(server) + +for _, f := range s.Fields() { + fmt.Printf("field name: %+v\n", f.Name()) + + if f.IsExported() { + fmt.Printf("value : %+v\n", f.Value()) + fmt.Printf("is zero : %+v\n", f.IsZero()) + } +} +``` + +## Credits + + * [Fatih Arslan](https://github.com/fatih) + * [Cihangir Savas](https://github.com/cihangir) + +## License + +The MIT License (MIT) - see LICENSE.md for more details diff --git a/vendor/github.com/fatih/structs/field.go b/vendor/github.com/fatih/structs/field.go new file mode 100644 index 0000000000..e69783230b --- /dev/null +++ b/vendor/github.com/fatih/structs/field.go @@ -0,0 +1,141 @@ +package structs + +import ( + "errors" + "fmt" + "reflect" +) + +var ( + errNotExported = errors.New("field is not exported") + errNotSettable = errors.New("field is not settable") +) + +// Field represents a single struct field that encapsulates high level +// functions around the field. +type Field struct { + value reflect.Value + field reflect.StructField + defaultTag string +} + +// Tag returns the value associated with key in the tag string. If there is no +// such key in the tag, Tag returns the empty string. +func (f *Field) Tag(key string) string { + return f.field.Tag.Get(key) +} + +// Value returns the underlying value of the field. It panics if the field +// is not exported. +func (f *Field) Value() interface{} { + return f.value.Interface() +} + +// IsEmbedded returns true if the given field is an anonymous field (embedded) +func (f *Field) IsEmbedded() bool { + return f.field.Anonymous +} + +// IsExported returns true if the given field is exported. +func (f *Field) IsExported() bool { + return f.field.PkgPath == "" +} + +// IsZero returns true if the given field is not initialized (has a zero value). +// It panics if the field is not exported. +func (f *Field) IsZero() bool { + zero := reflect.Zero(f.value.Type()).Interface() + current := f.Value() + + return reflect.DeepEqual(current, zero) +} + +// Name returns the name of the given field +func (f *Field) Name() string { + return f.field.Name +} + +// Kind returns the fields kind, such as "string", "map", "bool", etc .. +func (f *Field) Kind() reflect.Kind { + return f.value.Kind() +} + +// Set sets the field to given value v. It returns an error if the field is not +// settable (not addressable or not exported) or if the given value's type +// doesn't match the fields type. +func (f *Field) Set(val interface{}) error { + // we can't set unexported fields, so be sure this field is exported + if !f.IsExported() { + return errNotExported + } + + // do we get here? not sure... + if !f.value.CanSet() { + return errNotSettable + } + + given := reflect.ValueOf(val) + + if f.value.Kind() != given.Kind() { + return fmt.Errorf("wrong kind. got: %s want: %s", given.Kind(), f.value.Kind()) + } + + f.value.Set(given) + return nil +} + +// Zero sets the field to its zero value. It returns an error if the field is not +// settable (not addressable or not exported). +func (f *Field) Zero() error { + zero := reflect.Zero(f.value.Type()).Interface() + return f.Set(zero) +} + +// Fields returns a slice of Fields. This is particular handy to get the fields +// of a nested struct . A struct tag with the content of "-" ignores the +// checking of that particular field. Example: +// +// // Field is ignored by this package. +// Field *http.Request `structs:"-"` +// +// It panics if field is not exported or if field's kind is not struct +func (f *Field) Fields() []*Field { + return getFields(f.value, f.defaultTag) +} + +// Field returns the field from a nested struct. It panics if the nested struct +// is not exported or if the field was not found. +func (f *Field) Field(name string) *Field { + field, ok := f.FieldOk(name) + if !ok { + panic("field not found") + } + + return field +} + +// FieldOk returns the field from a nested struct. The boolean returns whether +// the field was found (true) or not (false). +func (f *Field) FieldOk(name string) (*Field, bool) { + value := &f.value + // value must be settable so we need to make sure it holds the address of the + // variable and not a copy, so we can pass the pointer to strctVal instead of a + // copy (which is not assigned to any variable, hence not settable). + // see "https://blog.golang.org/laws-of-reflection#TOC_8." + if f.value.Kind() != reflect.Ptr { + a := f.value.Addr() + value = &a + } + v := strctVal(value.Interface()) + t := v.Type() + + field, ok := t.FieldByName(name) + if !ok { + return nil, false + } + + return &Field{ + field: field, + value: v.FieldByName(name), + }, true +} diff --git a/vendor/github.com/fatih/structs/structs.go b/vendor/github.com/fatih/structs/structs.go new file mode 100644 index 0000000000..3a87706525 --- /dev/null +++ b/vendor/github.com/fatih/structs/structs.go @@ -0,0 +1,584 @@ +// Package structs contains various utilities functions to work with structs. +package structs + +import ( + "fmt" + + "reflect" +) + +var ( + // DefaultTagName is the default tag name for struct fields which provides + // a more granular to tweak certain structs. Lookup the necessary functions + // for more info. + DefaultTagName = "structs" // struct's field default tag name +) + +// Struct encapsulates a struct type to provide several high level functions +// around the struct. +type Struct struct { + raw interface{} + value reflect.Value + TagName string +} + +// New returns a new *Struct with the struct s. It panics if the s's kind is +// not struct. +func New(s interface{}) *Struct { + return &Struct{ + raw: s, + value: strctVal(s), + TagName: DefaultTagName, + } +} + +// Map converts the given struct to a map[string]interface{}, where the keys +// of the map are the field names and the values of the map the associated +// values of the fields. The default key string is the struct field name but +// can be changed in the struct field's tag value. The "structs" key in the +// struct's field tag value is the key name. Example: +// +// // Field appears in map as key "myName". +// Name string `structs:"myName"` +// +// A tag value with the content of "-" ignores that particular field. Example: +// +// // Field is ignored by this package. +// Field bool `structs:"-"` +// +// A tag value with the content of "string" uses the stringer to get the value. Example: +// +// // The value will be output of Animal's String() func. +// // Map will panic if Animal does not implement String(). +// Field *Animal `structs:"field,string"` +// +// A tag value with the option of "flatten" used in a struct field is to flatten its fields +// in the output map. Example: +// +// // The FieldStruct's fields will be flattened into the output map. +// FieldStruct time.Time `structs:",flatten"` +// +// A tag value with the option of "omitnested" stops iterating further if the type +// is a struct. Example: +// +// // Field is not processed further by this package. +// Field time.Time `structs:"myName,omitnested"` +// Field *http.Request `structs:",omitnested"` +// +// A tag value with the option of "omitempty" ignores that particular field if +// the field value is empty. Example: +// +// // Field appears in map as key "myName", but the field is +// // skipped if empty. +// Field string `structs:"myName,omitempty"` +// +// // Field appears in map as key "Field" (the default), but +// // the field is skipped if empty. +// Field string `structs:",omitempty"` +// +// Note that only exported fields of a struct can be accessed, non exported +// fields will be neglected. +func (s *Struct) Map() map[string]interface{} { + out := make(map[string]interface{}) + s.FillMap(out) + return out +} + +// FillMap is the same as Map. Instead of returning the output, it fills the +// given map. +func (s *Struct) FillMap(out map[string]interface{}) { + if out == nil { + return + } + + fields := s.structFields() + + for _, field := range fields { + name := field.Name + val := s.value.FieldByName(name) + isSubStruct := false + var finalVal interface{} + + tagName, tagOpts := parseTag(field.Tag.Get(s.TagName)) + if tagName != "" { + name = tagName + } + + // if the value is a zero value and the field is marked as omitempty do + // not include + if tagOpts.Has("omitempty") { + zero := reflect.Zero(val.Type()).Interface() + current := val.Interface() + + if reflect.DeepEqual(current, zero) { + continue + } + } + + if !tagOpts.Has("omitnested") { + finalVal = s.nested(val) + + v := reflect.ValueOf(val.Interface()) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + switch v.Kind() { + case reflect.Map, reflect.Struct: + isSubStruct = true + } + } else { + finalVal = val.Interface() + } + + if tagOpts.Has("string") { + s, ok := val.Interface().(fmt.Stringer) + if ok { + out[name] = s.String() + } + continue + } + + if isSubStruct && (tagOpts.Has("flatten")) { + for k := range finalVal.(map[string]interface{}) { + out[k] = finalVal.(map[string]interface{})[k] + } + } else { + out[name] = finalVal + } + } +} + +// Values converts the given s struct's field values to a []interface{}. A +// struct tag with the content of "-" ignores the that particular field. +// Example: +// +// // Field is ignored by this package. +// Field int `structs:"-"` +// +// A value with the option of "omitnested" stops iterating further if the type +// is a struct. Example: +// +// // Fields is not processed further by this package. +// Field time.Time `structs:",omitnested"` +// Field *http.Request `structs:",omitnested"` +// +// A tag value with the option of "omitempty" ignores that particular field and +// is not added to the values if the field value is empty. Example: +// +// // Field is skipped if empty +// Field string `structs:",omitempty"` +// +// Note that only exported fields of a struct can be accessed, non exported +// fields will be neglected. +func (s *Struct) Values() []interface{} { + fields := s.structFields() + + var t []interface{} + + for _, field := range fields { + val := s.value.FieldByName(field.Name) + + _, tagOpts := parseTag(field.Tag.Get(s.TagName)) + + // if the value is a zero value and the field is marked as omitempty do + // not include + if tagOpts.Has("omitempty") { + zero := reflect.Zero(val.Type()).Interface() + current := val.Interface() + + if reflect.DeepEqual(current, zero) { + continue + } + } + + if tagOpts.Has("string") { + s, ok := val.Interface().(fmt.Stringer) + if ok { + t = append(t, s.String()) + } + continue + } + + if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { + // look out for embedded structs, and convert them to a + // []interface{} to be added to the final values slice + t = append(t, Values(val.Interface())...) + } else { + t = append(t, val.Interface()) + } + } + + return t +} + +// Fields returns a slice of Fields. A struct tag with the content of "-" +// ignores the checking of that particular field. Example: +// +// // Field is ignored by this package. +// Field bool `structs:"-"` +// +// It panics if s's kind is not struct. +func (s *Struct) Fields() []*Field { + return getFields(s.value, s.TagName) +} + +// Names returns a slice of field names. A struct tag with the content of "-" +// ignores the checking of that particular field. Example: +// +// // Field is ignored by this package. +// Field bool `structs:"-"` +// +// It panics if s's kind is not struct. +func (s *Struct) Names() []string { + fields := getFields(s.value, s.TagName) + + names := make([]string, len(fields)) + + for i, field := range fields { + names[i] = field.Name() + } + + return names +} + +func getFields(v reflect.Value, tagName string) []*Field { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + t := v.Type() + + var fields []*Field + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + + if tag := field.Tag.Get(tagName); tag == "-" { + continue + } + + f := &Field{ + field: field, + value: v.FieldByName(field.Name), + } + + fields = append(fields, f) + + } + + return fields +} + +// Field returns a new Field struct that provides several high level functions +// around a single struct field entity. It panics if the field is not found. +func (s *Struct) Field(name string) *Field { + f, ok := s.FieldOk(name) + if !ok { + panic("field not found") + } + + return f +} + +// FieldOk returns a new Field struct that provides several high level functions +// around a single struct field entity. The boolean returns true if the field +// was found. +func (s *Struct) FieldOk(name string) (*Field, bool) { + t := s.value.Type() + + field, ok := t.FieldByName(name) + if !ok { + return nil, false + } + + return &Field{ + field: field, + value: s.value.FieldByName(name), + defaultTag: s.TagName, + }, true +} + +// IsZero returns true if all fields in a struct is a zero value (not +// initialized) A struct tag with the content of "-" ignores the checking of +// that particular field. Example: +// +// // Field is ignored by this package. +// Field bool `structs:"-"` +// +// A value with the option of "omitnested" stops iterating further if the type +// is a struct. Example: +// +// // Field is not processed further by this package. +// Field time.Time `structs:"myName,omitnested"` +// Field *http.Request `structs:",omitnested"` +// +// Note that only exported fields of a struct can be accessed, non exported +// fields will be neglected. It panics if s's kind is not struct. +func (s *Struct) IsZero() bool { + fields := s.structFields() + + for _, field := range fields { + val := s.value.FieldByName(field.Name) + + _, tagOpts := parseTag(field.Tag.Get(s.TagName)) + + if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { + ok := IsZero(val.Interface()) + if !ok { + return false + } + + continue + } + + // zero value of the given field, such as "" for string, 0 for int + zero := reflect.Zero(val.Type()).Interface() + + // current value of the given field + current := val.Interface() + + if !reflect.DeepEqual(current, zero) { + return false + } + } + + return true +} + +// HasZero returns true if a field in a struct is not initialized (zero value). +// A struct tag with the content of "-" ignores the checking of that particular +// field. Example: +// +// // Field is ignored by this package. +// Field bool `structs:"-"` +// +// A value with the option of "omitnested" stops iterating further if the type +// is a struct. Example: +// +// // Field is not processed further by this package. +// Field time.Time `structs:"myName,omitnested"` +// Field *http.Request `structs:",omitnested"` +// +// Note that only exported fields of a struct can be accessed, non exported +// fields will be neglected. It panics if s's kind is not struct. +func (s *Struct) HasZero() bool { + fields := s.structFields() + + for _, field := range fields { + val := s.value.FieldByName(field.Name) + + _, tagOpts := parseTag(field.Tag.Get(s.TagName)) + + if IsStruct(val.Interface()) && !tagOpts.Has("omitnested") { + ok := HasZero(val.Interface()) + if ok { + return true + } + + continue + } + + // zero value of the given field, such as "" for string, 0 for int + zero := reflect.Zero(val.Type()).Interface() + + // current value of the given field + current := val.Interface() + + if reflect.DeepEqual(current, zero) { + return true + } + } + + return false +} + +// Name returns the structs's type name within its package. For more info refer +// to Name() function. +func (s *Struct) Name() string { + return s.value.Type().Name() +} + +// structFields returns the exported struct fields for a given s struct. This +// is a convenient helper method to avoid duplicate code in some of the +// functions. +func (s *Struct) structFields() []reflect.StructField { + t := s.value.Type() + + var f []reflect.StructField + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + // we can't access the value of unexported fields + if field.PkgPath != "" { + continue + } + + // don't check if it's omitted + if tag := field.Tag.Get(s.TagName); tag == "-" { + continue + } + + f = append(f, field) + } + + return f +} + +func strctVal(s interface{}) reflect.Value { + v := reflect.ValueOf(s) + + // if pointer get the underlying element≤ + for v.Kind() == reflect.Ptr { + v = v.Elem() + } + + if v.Kind() != reflect.Struct { + panic("not struct") + } + + return v +} + +// Map converts the given struct to a map[string]interface{}. For more info +// refer to Struct types Map() method. It panics if s's kind is not struct. +func Map(s interface{}) map[string]interface{} { + return New(s).Map() +} + +// FillMap is the same as Map. Instead of returning the output, it fills the +// given map. +func FillMap(s interface{}, out map[string]interface{}) { + New(s).FillMap(out) +} + +// Values converts the given struct to a []interface{}. For more info refer to +// Struct types Values() method. It panics if s's kind is not struct. +func Values(s interface{}) []interface{} { + return New(s).Values() +} + +// Fields returns a slice of *Field. For more info refer to Struct types +// Fields() method. It panics if s's kind is not struct. +func Fields(s interface{}) []*Field { + return New(s).Fields() +} + +// Names returns a slice of field names. For more info refer to Struct types +// Names() method. It panics if s's kind is not struct. +func Names(s interface{}) []string { + return New(s).Names() +} + +// IsZero returns true if all fields is equal to a zero value. For more info +// refer to Struct types IsZero() method. It panics if s's kind is not struct. +func IsZero(s interface{}) bool { + return New(s).IsZero() +} + +// HasZero returns true if any field is equal to a zero value. For more info +// refer to Struct types HasZero() method. It panics if s's kind is not struct. +func HasZero(s interface{}) bool { + return New(s).HasZero() +} + +// IsStruct returns true if the given variable is a struct or a pointer to +// struct. +func IsStruct(s interface{}) bool { + v := reflect.ValueOf(s) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + // uninitialized zero value of a struct + if v.Kind() == reflect.Invalid { + return false + } + + return v.Kind() == reflect.Struct +} + +// Name returns the structs's type name within its package. It returns an +// empty string for unnamed types. It panics if s's kind is not struct. +func Name(s interface{}) string { + return New(s).Name() +} + +// nested retrieves recursively all types for the given value and returns the +// nested value. +func (s *Struct) nested(val reflect.Value) interface{} { + var finalVal interface{} + + v := reflect.ValueOf(val.Interface()) + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + switch v.Kind() { + case reflect.Struct: + n := New(val.Interface()) + n.TagName = s.TagName + m := n.Map() + + // do not add the converted value if there are no exported fields, ie: + // time.Time + if len(m) == 0 { + finalVal = val.Interface() + } else { + finalVal = m + } + case reflect.Map: + // get the element type of the map + mapElem := val.Type() + switch val.Type().Kind() { + case reflect.Ptr, reflect.Array, reflect.Map, + reflect.Slice, reflect.Chan: + mapElem = val.Type().Elem() + if mapElem.Kind() == reflect.Ptr { + mapElem = mapElem.Elem() + } + } + + // only iterate over struct types, ie: map[string]StructType, + // map[string][]StructType, + if mapElem.Kind() == reflect.Struct || + (mapElem.Kind() == reflect.Slice && + mapElem.Elem().Kind() == reflect.Struct) { + m := make(map[string]interface{}, val.Len()) + for _, k := range val.MapKeys() { + m[k.String()] = s.nested(val.MapIndex(k)) + } + finalVal = m + break + } + + // TODO(arslan): should this be optional? + finalVal = val.Interface() + case reflect.Slice, reflect.Array: + if val.Type().Kind() == reflect.Interface { + finalVal = val.Interface() + break + } + + // TODO(arslan): should this be optional? + // do not iterate of non struct types, just pass the value. Ie: []int, + // []string, co... We only iterate further if it's a struct. + // i.e []foo or []*foo + if val.Type().Elem().Kind() != reflect.Struct && + !(val.Type().Elem().Kind() == reflect.Ptr && + val.Type().Elem().Elem().Kind() == reflect.Struct) { + finalVal = val.Interface() + break + } + + slices := make([]interface{}, val.Len()) + for x := 0; x < val.Len(); x++ { + slices[x] = s.nested(val.Index(x)) + } + finalVal = slices + default: + finalVal = val.Interface() + } + + return finalVal +} diff --git a/vendor/github.com/fatih/structs/tags.go b/vendor/github.com/fatih/structs/tags.go new file mode 100644 index 0000000000..136a31eba9 --- /dev/null +++ b/vendor/github.com/fatih/structs/tags.go @@ -0,0 +1,32 @@ +package structs + +import "strings" + +// tagOptions contains a slice of tag options +type tagOptions []string + +// Has returns true if the given option is available in tagOptions +func (t tagOptions) Has(opt string) bool { + for _, tagOpt := range t { + if tagOpt == opt { + return true + } + } + + return false +} + +// parseTag splits a struct field's tag into its name and a list of options +// which comes after a name. A tag is in the form of: "name,option1,option2". +// The name can be neglectected. +func parseTag(tag string) (string, tagOptions) { + // tag is one of followings: + // "" + // "name" + // "name,opt" + // "name,opt,opt2" + // ",opt" + + res := strings.Split(tag, ",") + return res[0], res[1:] +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/.gitignore b/vendor/github.com/golang-jwt/jwt/v4/.gitignore new file mode 100644 index 0000000000..09573e0169 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/.gitignore @@ -0,0 +1,4 @@ +.DS_Store +bin +.idea/ + diff --git a/vendor/github.com/golang-jwt/jwt/v4/LICENSE b/vendor/github.com/golang-jwt/jwt/v4/LICENSE new file mode 100644 index 0000000000..35dbc25204 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/LICENSE @@ -0,0 +1,9 @@ +Copyright (c) 2012 Dave Grijalva +Copyright (c) 2021 golang-jwt maintainers + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + diff --git a/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md b/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md new file mode 100644 index 0000000000..32966f5981 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/MIGRATION_GUIDE.md @@ -0,0 +1,22 @@ +## Migration Guide (v4.0.0) + +Starting from [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0), the import path will be: + + "github.com/golang-jwt/jwt/v4" + +The `/v4` version will be backwards compatible with existing `v3.x.y` tags in this repo, as well as +`github.com/dgrijalva/jwt-go`. For most users this should be a drop-in replacement, if you're having +troubles migrating, please open an issue. + +You can replace all occurrences of `github.com/dgrijalva/jwt-go` or `github.com/golang-jwt/jwt` with `github.com/golang-jwt/jwt/v4`, either manually or by using tools such as `sed` or `gofmt`. + +And then you'd typically run: + +``` +go get github.com/golang-jwt/jwt/v4 +go mod tidy +``` + +## Older releases (before v3.2.0) + +The original migration guide for older releases can be found at https://github.com/dgrijalva/jwt-go/blob/master/MIGRATION_GUIDE.md. diff --git a/vendor/github.com/golang-jwt/jwt/v4/README.md b/vendor/github.com/golang-jwt/jwt/v4/README.md new file mode 100644 index 0000000000..30f2f2a6f7 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/README.md @@ -0,0 +1,138 @@ +# jwt-go + +[![build](https://github.com/golang-jwt/jwt/actions/workflows/build.yml/badge.svg)](https://github.com/golang-jwt/jwt/actions/workflows/build.yml) +[![Go Reference](https://pkg.go.dev/badge/github.com/golang-jwt/jwt/v4.svg)](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) + +A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](https://datatracker.ietf.org/doc/html/rfc7519). + +Starting with [v4.0.0](https://github.com/golang-jwt/jwt/releases/tag/v4.0.0) this project adds Go module support, but maintains backwards compatibility with older `v3.x.y` tags and upstream `github.com/dgrijalva/jwt-go`. +See the [`MIGRATION_GUIDE.md`](./MIGRATION_GUIDE.md) for more information. + +> After the original author of the library suggested migrating the maintenance of `jwt-go`, a dedicated team of open source maintainers decided to clone the existing library into this repository. See [dgrijalva/jwt-go#462](https://github.com/dgrijalva/jwt-go/issues/462) for a detailed discussion on this topic. + + +**SECURITY NOTICE:** Some older versions of Go have a security issue in the crypto/elliptic. Recommendation is to upgrade to at least 1.15 See issue [dgrijalva/jwt-go#216](https://github.com/dgrijalva/jwt-go/issues/216) for more detail. + +**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided. + +### Supported Go versions + +Our support of Go versions is aligned with Go's [version release policy](https://golang.org/doc/devel/release#policy). +So we will support a major version of Go until there are two newer major releases. +We no longer support building jwt-go with unsupported Go versions, as these contain security vulnerabilities +which will not be fixed. + +## What the heck is a JWT? + +JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens. + +In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](https://datatracker.ietf.org/doc/html/rfc4648) encoded. The last part is the signature, encoded the same way. + +The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used. + +The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) for information about reserved keys and the proper way to add your own. + +## What's in the box? + +This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own. + +## Installation Guidelines + +1. To install the jwt package, you first need to have [Go](https://go.dev/doc/install) installed, then you can use the command below to add `jwt-go` as a dependency in your Go program. + +```sh +go get -u github.com/golang-jwt/jwt/v4 +``` + +2. Import it in your code: + +```go +import "github.com/golang-jwt/jwt/v4" +``` + +## Examples + +See [the project documentation](https://pkg.go.dev/github.com/golang-jwt/jwt/v4) for examples of usage: + +* [Simple example of parsing and validating a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-Parse-Hmac) +* [Simple example of building and signing a token](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#example-New-Hmac) +* [Directory of Examples](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#pkg-examples) + +## Extensions + +This library publishes all the necessary components for adding your own signing methods or key functions. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod` or provide a `jwt.Keyfunc`. + +A common use case would be integrating with different 3rd party signature providers, like key management services from various cloud providers or Hardware Security Modules (HSMs) or to implement additional standards. + +| Extension | Purpose | Repo | +| --------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------ | +| GCP | Integrates with multiple Google Cloud Platform signing tools (AppEngine, IAM API, Cloud KMS) | https://github.com/someone1/gcp-jwt-go | +| AWS | Integrates with AWS Key Management Service, KMS | https://github.com/matelang/jwt-go-aws-kms | +| JWKS | Provides support for JWKS ([RFC 7517](https://datatracker.ietf.org/doc/html/rfc7517)) as a `jwt.Keyfunc` | https://github.com/MicahParks/keyfunc | + +*Disclaimer*: Unless otherwise specified, these integrations are maintained by third parties and should not be considered as a primary offer by any of the mentioned cloud providers + +## Compliance + +This library was last reviewed to comply with [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519) dated May 2015 with a few notable differences: + +* In order to protect against accidental use of [Unsecured JWTs](https://datatracker.ietf.org/doc/html/rfc7519#section-6), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key. + +## Project Status & Versioning + +This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason). + +This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `main`. Periodically, versions will be tagged from `main`. You can find all the releases on [the project releases page](https://github.com/golang-jwt/jwt/releases). + +**BREAKING CHANGES:*** +A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code. + +## Usage Tips + +### Signing vs Encryption + +A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data: + +* The author of the token was in the possession of the signing secret +* The data has not been modified since it was signed + +It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. The companion project https://github.com/golang-jwt/jwe aims at a (very) experimental implementation of the JWE standard. + +### Choosing a Signing Method + +There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric. + +Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation. + +Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification. + +### Signing Methods and Key Types + +Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones: + +* The [HMAC signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation +* The [RSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation +* The [ECDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation +* The [EdDSA signing method](https://pkg.go.dev/github.com/golang-jwt/jwt/v4#SigningMethodEd25519) (`Ed25519`) expect `ed25519.PrivateKey` for signing and `ed25519.PublicKey` for validation + +### JWT and OAuth + +It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication. + +Without going too far down the rabbit hole, here's a description of the interaction of these technologies: + +* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth. +* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token. +* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL. + +### Troubleshooting + +This library uses descriptive error messages whenever possible. If you are not getting the expected result, have a look at the errors. The most common place people get stuck is providing the correct type of key to the parser. See the above section on signing methods and key types. + +## More + +Documentation can be found [on pkg.go.dev](https://pkg.go.dev/github.com/golang-jwt/jwt/v4). + +The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation. + +[golang-jwt](https://github.com/orgs/golang-jwt) incorporates a modified version of the JWT logo, which is distributed under the terms of the [MIT License](https://github.com/jsonwebtoken/jsonwebtoken.github.io/blob/master/LICENSE.txt). diff --git a/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md b/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md new file mode 100644 index 0000000000..b08402c342 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/SECURITY.md @@ -0,0 +1,19 @@ +# Security Policy + +## Supported Versions + +As of February 2022 (and until this document is updated), the latest version `v4` is supported. + +## Reporting a Vulnerability + +If you think you found a vulnerability, and even if you are not sure, please report it to jwt-go-security@googlegroups.com or one of the other [golang-jwt maintainers](https://github.com/orgs/golang-jwt/people). Please try be explicit, describe steps to reproduce the security issue with code example(s). + +You will receive a response within a timely manner. If the issue is confirmed, we will do our best to release a patch as soon as possible given the complexity of the problem. + +## Public Discussions + +Please avoid publicly discussing a potential security vulnerability. + +Let's take this offline and find a solution first, this limits the potential impact as much as possible. + +We appreciate your help! diff --git a/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md b/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md new file mode 100644 index 0000000000..afbfc4e408 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/VERSION_HISTORY.md @@ -0,0 +1,135 @@ +## `jwt-go` Version History + +#### 4.0.0 + +* Introduces support for Go modules. The `v4` version will be backwards compatible with `v3.x.y`. + +#### 3.2.2 + +* Starting from this release, we are adopting the policy to support the most 2 recent versions of Go currently available. By the time of this release, this is Go 1.15 and 1.16 ([#28](https://github.com/golang-jwt/jwt/pull/28)). +* Fixed a potential issue that could occur when the verification of `exp`, `iat` or `nbf` was not required and contained invalid contents, i.e. non-numeric/date. Thanks for @thaJeztah for making us aware of that and @giorgos-f3 for originally reporting it to the formtech fork ([#40](https://github.com/golang-jwt/jwt/pull/40)). +* Added support for EdDSA / ED25519 ([#36](https://github.com/golang-jwt/jwt/pull/36)). +* Optimized allocations ([#33](https://github.com/golang-jwt/jwt/pull/33)). + +#### 3.2.1 + +* **Import Path Change**: See MIGRATION_GUIDE.md for tips on updating your code + * Changed the import path from `github.com/dgrijalva/jwt-go` to `github.com/golang-jwt/jwt` +* Fixed type confusing issue between `string` and `[]string` in `VerifyAudience` ([#12](https://github.com/golang-jwt/jwt/pull/12)). This fixes CVE-2020-26160 + +#### 3.2.0 + +* Added method `ParseUnverified` to allow users to split up the tasks of parsing and validation +* HMAC signing method returns `ErrInvalidKeyType` instead of `ErrInvalidKey` where appropriate +* Added options to `request.ParseFromRequest`, which allows for an arbitrary list of modifiers to parsing behavior. Initial set include `WithClaims` and `WithParser`. Existing usage of this function will continue to work as before. +* Deprecated `ParseFromRequestWithClaims` to simplify API in the future. + +#### 3.1.0 + +* Improvements to `jwt` command line tool +* Added `SkipClaimsValidation` option to `Parser` +* Documentation updates + +#### 3.0.0 + +* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code + * Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods. + * `ParseFromRequest` has been moved to `request` subpackage and usage has changed + * The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims. +* Other Additions and Changes + * Added `Claims` interface type to allow users to decode the claims into a custom type + * Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into. + * Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage + * Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims` + * Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`. + * Added several new, more specific, validation errors to error type bitmask + * Moved examples from README to executable example files + * Signing method registry is now thread safe + * Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser) + +#### 2.7.0 + +This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes. + +* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying +* Error text for expired tokens includes how long it's been expired +* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM` +* Documentation updates + +#### 2.6.0 + +* Exposed inner error within ValidationError +* Fixed validation errors when using UseJSONNumber flag +* Added several unit tests + +#### 2.5.0 + +* Added support for signing method none. You shouldn't use this. The API tries to make this clear. +* Updated/fixed some documentation +* Added more helpful error message when trying to parse tokens that begin with `BEARER ` + +#### 2.4.0 + +* Added new type, Parser, to allow for configuration of various parsing parameters + * You can now specify a list of valid signing methods. Anything outside this set will be rejected. + * You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON +* Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go) +* Fixed some bugs with ECDSA parsing + +#### 2.3.0 + +* Added support for ECDSA signing methods +* Added support for RSA PSS signing methods (requires go v1.4) + +#### 2.2.0 + +* Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic. + +#### 2.1.0 + +Backwards compatible API change that was missed in 2.0.0. + +* The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte` + +#### 2.0.0 + +There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change. + +The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`. + +It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`. + +* **Compatibility Breaking Changes** + * `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct` + * `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct` + * `KeyFunc` now returns `interface{}` instead of `[]byte` + * `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key + * `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key +* Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type. + * Added public package global `SigningMethodHS256` + * Added public package global `SigningMethodHS384` + * Added public package global `SigningMethodHS512` +* Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type. + * Added public package global `SigningMethodRS256` + * Added public package global `SigningMethodRS384` + * Added public package global `SigningMethodRS512` +* Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged. +* Refactored the RSA implementation to be easier to read +* Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM` + +#### 1.0.2 + +* Fixed bug in parsing public keys from certificates +* Added more tests around the parsing of keys for RS256 +* Code refactoring in RS256 implementation. No functional changes + +#### 1.0.1 + +* Fixed panic if RS256 signing method was passed an invalid key + +#### 1.0.0 + +* First versioned release +* API stabilized +* Supports creating, signing, parsing, and validating JWT tokens +* Supports RS256 and HS256 signing methods diff --git a/vendor/github.com/golang-jwt/jwt/v4/claims.go b/vendor/github.com/golang-jwt/jwt/v4/claims.go new file mode 100644 index 0000000000..364cec8773 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/claims.go @@ -0,0 +1,269 @@ +package jwt + +import ( + "crypto/subtle" + "fmt" + "time" +) + +// Claims must just have a Valid method that determines +// if the token is invalid for any supported reason +type Claims interface { + Valid() error +} + +// RegisteredClaims are a structured version of the JWT Claims Set, +// restricted to Registered Claim Names, as referenced at +// https://datatracker.ietf.org/doc/html/rfc7519#section-4.1 +// +// This type can be used on its own, but then additional private and +// public claims embedded in the JWT will not be parsed. The typical usecase +// therefore is to embedded this in a user-defined claim type. +// +// See examples for how to use this with your own claim types. +type RegisteredClaims struct { + // the `iss` (Issuer) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.1 + Issuer string `json:"iss,omitempty"` + + // the `sub` (Subject) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2 + Subject string `json:"sub,omitempty"` + + // the `aud` (Audience) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.3 + Audience ClaimStrings `json:"aud,omitempty"` + + // the `exp` (Expiration Time) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4 + ExpiresAt *NumericDate `json:"exp,omitempty"` + + // the `nbf` (Not Before) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5 + NotBefore *NumericDate `json:"nbf,omitempty"` + + // the `iat` (Issued At) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6 + IssuedAt *NumericDate `json:"iat,omitempty"` + + // the `jti` (JWT ID) claim. See https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.7 + ID string `json:"jti,omitempty"` +} + +// Valid validates time based claims "exp, iat, nbf". +// There is no accounting for clock skew. +// As well, if any of the above claims are not in the token, it will still +// be considered a valid claim. +func (c RegisteredClaims) Valid() error { + vErr := new(ValidationError) + now := TimeFunc() + + // The claims below are optional, by default, so if they are set to the + // default value in Go, let's not fail the verification for them. + if !c.VerifyExpiresAt(now, false) { + delta := now.Sub(c.ExpiresAt.Time) + vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta) + vErr.Errors |= ValidationErrorExpired + } + + if !c.VerifyIssuedAt(now, false) { + vErr.Inner = ErrTokenUsedBeforeIssued + vErr.Errors |= ValidationErrorIssuedAt + } + + if !c.VerifyNotBefore(now, false) { + vErr.Inner = ErrTokenNotValidYet + vErr.Errors |= ValidationErrorNotValidYet + } + + if vErr.valid() { + return nil + } + + return vErr +} + +// VerifyAudience compares the aud claim against cmp. +// If required is false, this method will return true if the value matches or is unset +func (c *RegisteredClaims) VerifyAudience(cmp string, req bool) bool { + return verifyAud(c.Audience, cmp, req) +} + +// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). +// If req is false, it will return true, if exp is unset. +func (c *RegisteredClaims) VerifyExpiresAt(cmp time.Time, req bool) bool { + if c.ExpiresAt == nil { + return verifyExp(nil, cmp, req) + } + + return verifyExp(&c.ExpiresAt.Time, cmp, req) +} + +// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). +// If req is false, it will return true, if iat is unset. +func (c *RegisteredClaims) VerifyIssuedAt(cmp time.Time, req bool) bool { + if c.IssuedAt == nil { + return verifyIat(nil, cmp, req) + } + + return verifyIat(&c.IssuedAt.Time, cmp, req) +} + +// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). +// If req is false, it will return true, if nbf is unset. +func (c *RegisteredClaims) VerifyNotBefore(cmp time.Time, req bool) bool { + if c.NotBefore == nil { + return verifyNbf(nil, cmp, req) + } + + return verifyNbf(&c.NotBefore.Time, cmp, req) +} + +// VerifyIssuer compares the iss claim against cmp. +// If required is false, this method will return true if the value matches or is unset +func (c *RegisteredClaims) VerifyIssuer(cmp string, req bool) bool { + return verifyIss(c.Issuer, cmp, req) +} + +// StandardClaims are a structured version of the JWT Claims Set, as referenced at +// https://datatracker.ietf.org/doc/html/rfc7519#section-4. They do not follow the +// specification exactly, since they were based on an earlier draft of the +// specification and not updated. The main difference is that they only +// support integer-based date fields and singular audiences. This might lead to +// incompatibilities with other JWT implementations. The use of this is discouraged, instead +// the newer RegisteredClaims struct should be used. +// +// Deprecated: Use RegisteredClaims instead for a forward-compatible way to access registered claims in a struct. +type StandardClaims struct { + Audience string `json:"aud,omitempty"` + ExpiresAt int64 `json:"exp,omitempty"` + Id string `json:"jti,omitempty"` + IssuedAt int64 `json:"iat,omitempty"` + Issuer string `json:"iss,omitempty"` + NotBefore int64 `json:"nbf,omitempty"` + Subject string `json:"sub,omitempty"` +} + +// Valid validates time based claims "exp, iat, nbf". There is no accounting for clock skew. +// As well, if any of the above claims are not in the token, it will still +// be considered a valid claim. +func (c StandardClaims) Valid() error { + vErr := new(ValidationError) + now := TimeFunc().Unix() + + // The claims below are optional, by default, so if they are set to the + // default value in Go, let's not fail the verification for them. + if !c.VerifyExpiresAt(now, false) { + delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) + vErr.Inner = fmt.Errorf("%s by %s", ErrTokenExpired, delta) + vErr.Errors |= ValidationErrorExpired + } + + if !c.VerifyIssuedAt(now, false) { + vErr.Inner = ErrTokenUsedBeforeIssued + vErr.Errors |= ValidationErrorIssuedAt + } + + if !c.VerifyNotBefore(now, false) { + vErr.Inner = ErrTokenNotValidYet + vErr.Errors |= ValidationErrorNotValidYet + } + + if vErr.valid() { + return nil + } + + return vErr +} + +// VerifyAudience compares the aud claim against cmp. +// If required is false, this method will return true if the value matches or is unset +func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool { + return verifyAud([]string{c.Audience}, cmp, req) +} + +// VerifyExpiresAt compares the exp claim against cmp (cmp < exp). +// If req is false, it will return true, if exp is unset. +func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool { + if c.ExpiresAt == 0 { + return verifyExp(nil, time.Unix(cmp, 0), req) + } + + t := time.Unix(c.ExpiresAt, 0) + return verifyExp(&t, time.Unix(cmp, 0), req) +} + +// VerifyIssuedAt compares the iat claim against cmp (cmp >= iat). +// If req is false, it will return true, if iat is unset. +func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool { + if c.IssuedAt == 0 { + return verifyIat(nil, time.Unix(cmp, 0), req) + } + + t := time.Unix(c.IssuedAt, 0) + return verifyIat(&t, time.Unix(cmp, 0), req) +} + +// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). +// If req is false, it will return true, if nbf is unset. +func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool { + if c.NotBefore == 0 { + return verifyNbf(nil, time.Unix(cmp, 0), req) + } + + t := time.Unix(c.NotBefore, 0) + return verifyNbf(&t, time.Unix(cmp, 0), req) +} + +// VerifyIssuer compares the iss claim against cmp. +// If required is false, this method will return true if the value matches or is unset +func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool { + return verifyIss(c.Issuer, cmp, req) +} + +// ----- helpers + +func verifyAud(aud []string, cmp string, required bool) bool { + if len(aud) == 0 { + return !required + } + // use a var here to keep constant time compare when looping over a number of claims + result := false + + var stringClaims string + for _, a := range aud { + if subtle.ConstantTimeCompare([]byte(a), []byte(cmp)) != 0 { + result = true + } + stringClaims = stringClaims + a + } + + // case where "" is sent in one or many aud claims + if len(stringClaims) == 0 { + return !required + } + + return result +} + +func verifyExp(exp *time.Time, now time.Time, required bool) bool { + if exp == nil { + return !required + } + return now.Before(*exp) +} + +func verifyIat(iat *time.Time, now time.Time, required bool) bool { + if iat == nil { + return !required + } + return now.After(*iat) || now.Equal(*iat) +} + +func verifyNbf(nbf *time.Time, now time.Time, required bool) bool { + if nbf == nil { + return !required + } + return now.After(*nbf) || now.Equal(*nbf) +} + +func verifyIss(iss string, cmp string, required bool) bool { + if iss == "" { + return !required + } + return subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/doc.go b/vendor/github.com/golang-jwt/jwt/v4/doc.go new file mode 100644 index 0000000000..a86dc1a3b3 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/doc.go @@ -0,0 +1,4 @@ +// Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html +// +// See README.md for more info. +package jwt diff --git a/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go b/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go new file mode 100644 index 0000000000..eac023fc6c --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/ecdsa.go @@ -0,0 +1,142 @@ +package jwt + +import ( + "crypto" + "crypto/ecdsa" + "crypto/rand" + "errors" + "math/big" +) + +var ( + // Sadly this is missing from crypto/ecdsa compared to crypto/rsa + ErrECDSAVerification = errors.New("crypto/ecdsa: verification error") +) + +// SigningMethodECDSA implements the ECDSA family of signing methods. +// Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification +type SigningMethodECDSA struct { + Name string + Hash crypto.Hash + KeySize int + CurveBits int +} + +// Specific instances for EC256 and company +var ( + SigningMethodES256 *SigningMethodECDSA + SigningMethodES384 *SigningMethodECDSA + SigningMethodES512 *SigningMethodECDSA +) + +func init() { + // ES256 + SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256} + RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod { + return SigningMethodES256 + }) + + // ES384 + SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384} + RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod { + return SigningMethodES384 + }) + + // ES512 + SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521} + RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod { + return SigningMethodES512 + }) +} + +func (m *SigningMethodECDSA) Alg() string { + return m.Name +} + +// Verify implements token verification for the SigningMethod. +// For this verify method, key must be an ecdsa.PublicKey struct +func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error { + var err error + + // Decode the signature + var sig []byte + if sig, err = DecodeSegment(signature); err != nil { + return err + } + + // Get the key + var ecdsaKey *ecdsa.PublicKey + switch k := key.(type) { + case *ecdsa.PublicKey: + ecdsaKey = k + default: + return ErrInvalidKeyType + } + + if len(sig) != 2*m.KeySize { + return ErrECDSAVerification + } + + r := big.NewInt(0).SetBytes(sig[:m.KeySize]) + s := big.NewInt(0).SetBytes(sig[m.KeySize:]) + + // Create hasher + if !m.Hash.Available() { + return ErrHashUnavailable + } + hasher := m.Hash.New() + hasher.Write([]byte(signingString)) + + // Verify the signature + if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus { + return nil + } + + return ErrECDSAVerification +} + +// Sign implements token signing for the SigningMethod. +// For this signing method, key must be an ecdsa.PrivateKey struct +func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) { + // Get the key + var ecdsaKey *ecdsa.PrivateKey + switch k := key.(type) { + case *ecdsa.PrivateKey: + ecdsaKey = k + default: + return "", ErrInvalidKeyType + } + + // Create the hasher + if !m.Hash.Available() { + return "", ErrHashUnavailable + } + + hasher := m.Hash.New() + hasher.Write([]byte(signingString)) + + // Sign the string and return r, s + if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil { + curveBits := ecdsaKey.Curve.Params().BitSize + + if m.CurveBits != curveBits { + return "", ErrInvalidKey + } + + keyBytes := curveBits / 8 + if curveBits%8 > 0 { + keyBytes += 1 + } + + // We serialize the outputs (r and s) into big-endian byte arrays + // padded with zeros on the left to make sure the sizes work out. + // Output must be 2*keyBytes long. + out := make([]byte, 2*keyBytes) + r.FillBytes(out[0:keyBytes]) // r is assigned to the first half of output. + s.FillBytes(out[keyBytes:]) // s is assigned to the second half of output. + + return EncodeSegment(out), nil + } else { + return "", err + } +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go b/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go new file mode 100644 index 0000000000..5700636d35 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/ecdsa_utils.go @@ -0,0 +1,69 @@ +package jwt + +import ( + "crypto/ecdsa" + "crypto/x509" + "encoding/pem" + "errors" +) + +var ( + ErrNotECPublicKey = errors.New("key is not a valid ECDSA public key") + ErrNotECPrivateKey = errors.New("key is not a valid ECDSA private key") +) + +// ParseECPrivateKeyFromPEM parses a PEM encoded Elliptic Curve Private Key Structure +func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil { + if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { + return nil, err + } + } + + var pkey *ecdsa.PrivateKey + var ok bool + if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok { + return nil, ErrNotECPrivateKey + } + + return pkey, nil +} + +// ParseECPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key +func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { + if cert, err := x509.ParseCertificate(block.Bytes); err == nil { + parsedKey = cert.PublicKey + } else { + return nil, err + } + } + + var pkey *ecdsa.PublicKey + var ok bool + if pkey, ok = parsedKey.(*ecdsa.PublicKey); !ok { + return nil, ErrNotECPublicKey + } + + return pkey, nil +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ed25519.go b/vendor/github.com/golang-jwt/jwt/v4/ed25519.go new file mode 100644 index 0000000000..07d3aacd63 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/ed25519.go @@ -0,0 +1,85 @@ +package jwt + +import ( + "errors" + + "crypto" + "crypto/ed25519" + "crypto/rand" +) + +var ( + ErrEd25519Verification = errors.New("ed25519: verification error") +) + +// SigningMethodEd25519 implements the EdDSA family. +// Expects ed25519.PrivateKey for signing and ed25519.PublicKey for verification +type SigningMethodEd25519 struct{} + +// Specific instance for EdDSA +var ( + SigningMethodEdDSA *SigningMethodEd25519 +) + +func init() { + SigningMethodEdDSA = &SigningMethodEd25519{} + RegisterSigningMethod(SigningMethodEdDSA.Alg(), func() SigningMethod { + return SigningMethodEdDSA + }) +} + +func (m *SigningMethodEd25519) Alg() string { + return "EdDSA" +} + +// Verify implements token verification for the SigningMethod. +// For this verify method, key must be an ed25519.PublicKey +func (m *SigningMethodEd25519) Verify(signingString, signature string, key interface{}) error { + var err error + var ed25519Key ed25519.PublicKey + var ok bool + + if ed25519Key, ok = key.(ed25519.PublicKey); !ok { + return ErrInvalidKeyType + } + + if len(ed25519Key) != ed25519.PublicKeySize { + return ErrInvalidKey + } + + // Decode the signature + var sig []byte + if sig, err = DecodeSegment(signature); err != nil { + return err + } + + // Verify the signature + if !ed25519.Verify(ed25519Key, []byte(signingString), sig) { + return ErrEd25519Verification + } + + return nil +} + +// Sign implements token signing for the SigningMethod. +// For this signing method, key must be an ed25519.PrivateKey +func (m *SigningMethodEd25519) Sign(signingString string, key interface{}) (string, error) { + var ed25519Key crypto.Signer + var ok bool + + if ed25519Key, ok = key.(crypto.Signer); !ok { + return "", ErrInvalidKeyType + } + + if _, ok := ed25519Key.Public().(ed25519.PublicKey); !ok { + return "", ErrInvalidKey + } + + // Sign the string and return the encoded result + // ed25519 performs a two-pass hash as part of its algorithm. Therefore, we need to pass a non-prehashed message into the Sign function, as indicated by crypto.Hash(0) + sig, err := ed25519Key.Sign(rand.Reader, []byte(signingString), crypto.Hash(0)) + if err != nil { + return "", err + } + return EncodeSegment(sig), nil +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go b/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go new file mode 100644 index 0000000000..cdb5e68e87 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/ed25519_utils.go @@ -0,0 +1,64 @@ +package jwt + +import ( + "crypto" + "crypto/ed25519" + "crypto/x509" + "encoding/pem" + "errors" +) + +var ( + ErrNotEdPrivateKey = errors.New("key is not a valid Ed25519 private key") + ErrNotEdPublicKey = errors.New("key is not a valid Ed25519 public key") +) + +// ParseEdPrivateKeyFromPEM parses a PEM-encoded Edwards curve private key +func ParseEdPrivateKeyFromPEM(key []byte) (crypto.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { + return nil, err + } + + var pkey ed25519.PrivateKey + var ok bool + if pkey, ok = parsedKey.(ed25519.PrivateKey); !ok { + return nil, ErrNotEdPrivateKey + } + + return pkey, nil +} + +// ParseEdPublicKeyFromPEM parses a PEM-encoded Edwards curve public key +func ParseEdPublicKeyFromPEM(key []byte) (crypto.PublicKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { + return nil, err + } + + var pkey ed25519.PublicKey + var ok bool + if pkey, ok = parsedKey.(ed25519.PublicKey); !ok { + return nil, ErrNotEdPublicKey + } + + return pkey, nil +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/errors.go b/vendor/github.com/golang-jwt/jwt/v4/errors.go new file mode 100644 index 0000000000..10ac8835cc --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/errors.go @@ -0,0 +1,112 @@ +package jwt + +import ( + "errors" +) + +// Error constants +var ( + ErrInvalidKey = errors.New("key is invalid") + ErrInvalidKeyType = errors.New("key is of invalid type") + ErrHashUnavailable = errors.New("the requested hash function is unavailable") + + ErrTokenMalformed = errors.New("token is malformed") + ErrTokenUnverifiable = errors.New("token is unverifiable") + ErrTokenSignatureInvalid = errors.New("token signature is invalid") + + ErrTokenInvalidAudience = errors.New("token has invalid audience") + ErrTokenExpired = errors.New("token is expired") + ErrTokenUsedBeforeIssued = errors.New("token used before issued") + ErrTokenInvalidIssuer = errors.New("token has invalid issuer") + ErrTokenNotValidYet = errors.New("token is not valid yet") + ErrTokenInvalidId = errors.New("token has invalid id") + ErrTokenInvalidClaims = errors.New("token has invalid claims") +) + +// The errors that might occur when parsing and validating a token +const ( + ValidationErrorMalformed uint32 = 1 << iota // Token is malformed + ValidationErrorUnverifiable // Token could not be verified because of signing problems + ValidationErrorSignatureInvalid // Signature validation failed + + // Standard Claim validation errors + ValidationErrorAudience // AUD validation failed + ValidationErrorExpired // EXP validation failed + ValidationErrorIssuedAt // IAT validation failed + ValidationErrorIssuer // ISS validation failed + ValidationErrorNotValidYet // NBF validation failed + ValidationErrorId // JTI validation failed + ValidationErrorClaimsInvalid // Generic claims validation error +) + +// NewValidationError is a helper for constructing a ValidationError with a string error message +func NewValidationError(errorText string, errorFlags uint32) *ValidationError { + return &ValidationError{ + text: errorText, + Errors: errorFlags, + } +} + +// ValidationError represents an error from Parse if token is not valid +type ValidationError struct { + Inner error // stores the error returned by external dependencies, i.e.: KeyFunc + Errors uint32 // bitfield. see ValidationError... constants + text string // errors that do not have a valid error just have text +} + +// Error is the implementation of the err interface. +func (e ValidationError) Error() string { + if e.Inner != nil { + return e.Inner.Error() + } else if e.text != "" { + return e.text + } else { + return "token is invalid" + } +} + +// Unwrap gives errors.Is and errors.As access to the inner error. +func (e *ValidationError) Unwrap() error { + return e.Inner +} + +// No errors +func (e *ValidationError) valid() bool { + return e.Errors == 0 +} + +// Is checks if this ValidationError is of the supplied error. We are first checking for the exact error message +// by comparing the inner error message. If that fails, we compare using the error flags. This way we can use +// custom error messages (mainly for backwards compatability) and still leverage errors.Is using the global error variables. +func (e *ValidationError) Is(err error) bool { + // Check, if our inner error is a direct match + if errors.Is(errors.Unwrap(e), err) { + return true + } + + // Otherwise, we need to match using our error flags + switch err { + case ErrTokenMalformed: + return e.Errors&ValidationErrorMalformed != 0 + case ErrTokenUnverifiable: + return e.Errors&ValidationErrorUnverifiable != 0 + case ErrTokenSignatureInvalid: + return e.Errors&ValidationErrorSignatureInvalid != 0 + case ErrTokenInvalidAudience: + return e.Errors&ValidationErrorAudience != 0 + case ErrTokenExpired: + return e.Errors&ValidationErrorExpired != 0 + case ErrTokenUsedBeforeIssued: + return e.Errors&ValidationErrorIssuedAt != 0 + case ErrTokenInvalidIssuer: + return e.Errors&ValidationErrorIssuer != 0 + case ErrTokenNotValidYet: + return e.Errors&ValidationErrorNotValidYet != 0 + case ErrTokenInvalidId: + return e.Errors&ValidationErrorId != 0 + case ErrTokenInvalidClaims: + return e.Errors&ValidationErrorClaimsInvalid != 0 + } + + return false +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/hmac.go b/vendor/github.com/golang-jwt/jwt/v4/hmac.go new file mode 100644 index 0000000000..011f68a274 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/hmac.go @@ -0,0 +1,95 @@ +package jwt + +import ( + "crypto" + "crypto/hmac" + "errors" +) + +// SigningMethodHMAC implements the HMAC-SHA family of signing methods. +// Expects key type of []byte for both signing and validation +type SigningMethodHMAC struct { + Name string + Hash crypto.Hash +} + +// Specific instances for HS256 and company +var ( + SigningMethodHS256 *SigningMethodHMAC + SigningMethodHS384 *SigningMethodHMAC + SigningMethodHS512 *SigningMethodHMAC + ErrSignatureInvalid = errors.New("signature is invalid") +) + +func init() { + // HS256 + SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256} + RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod { + return SigningMethodHS256 + }) + + // HS384 + SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384} + RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod { + return SigningMethodHS384 + }) + + // HS512 + SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512} + RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod { + return SigningMethodHS512 + }) +} + +func (m *SigningMethodHMAC) Alg() string { + return m.Name +} + +// Verify implements token verification for the SigningMethod. Returns nil if the signature is valid. +func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error { + // Verify the key is the right type + keyBytes, ok := key.([]byte) + if !ok { + return ErrInvalidKeyType + } + + // Decode signature, for comparison + sig, err := DecodeSegment(signature) + if err != nil { + return err + } + + // Can we use the specified hashing method? + if !m.Hash.Available() { + return ErrHashUnavailable + } + + // This signing method is symmetric, so we validate the signature + // by reproducing the signature from the signing string and key, then + // comparing that against the provided signature. + hasher := hmac.New(m.Hash.New, keyBytes) + hasher.Write([]byte(signingString)) + if !hmac.Equal(sig, hasher.Sum(nil)) { + return ErrSignatureInvalid + } + + // No validation errors. Signature is good. + return nil +} + +// Sign implements token signing for the SigningMethod. +// Key must be []byte +func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) { + if keyBytes, ok := key.([]byte); ok { + if !m.Hash.Available() { + return "", ErrHashUnavailable + } + + hasher := hmac.New(m.Hash.New, keyBytes) + hasher.Write([]byte(signingString)) + + return EncodeSegment(hasher.Sum(nil)), nil + } + + return "", ErrInvalidKeyType +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/map_claims.go b/vendor/github.com/golang-jwt/jwt/v4/map_claims.go new file mode 100644 index 0000000000..2700d64a0d --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/map_claims.go @@ -0,0 +1,151 @@ +package jwt + +import ( + "encoding/json" + "errors" + "time" + // "fmt" +) + +// MapClaims is a claims type that uses the map[string]interface{} for JSON decoding. +// This is the default claims type if you don't supply one +type MapClaims map[string]interface{} + +// VerifyAudience Compares the aud claim against cmp. +// If required is false, this method will return true if the value matches or is unset +func (m MapClaims) VerifyAudience(cmp string, req bool) bool { + var aud []string + switch v := m["aud"].(type) { + case string: + aud = append(aud, v) + case []string: + aud = v + case []interface{}: + for _, a := range v { + vs, ok := a.(string) + if !ok { + return false + } + aud = append(aud, vs) + } + } + return verifyAud(aud, cmp, req) +} + +// VerifyExpiresAt compares the exp claim against cmp (cmp <= exp). +// If req is false, it will return true, if exp is unset. +func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool { + cmpTime := time.Unix(cmp, 0) + + v, ok := m["exp"] + if !ok { + return !req + } + + switch exp := v.(type) { + case float64: + if exp == 0 { + return verifyExp(nil, cmpTime, req) + } + + return verifyExp(&newNumericDateFromSeconds(exp).Time, cmpTime, req) + case json.Number: + v, _ := exp.Float64() + + return verifyExp(&newNumericDateFromSeconds(v).Time, cmpTime, req) + } + + return false +} + +// VerifyIssuedAt compares the exp claim against cmp (cmp >= iat). +// If req is false, it will return true, if iat is unset. +func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool { + cmpTime := time.Unix(cmp, 0) + + v, ok := m["iat"] + if !ok { + return !req + } + + switch iat := v.(type) { + case float64: + if iat == 0 { + return verifyIat(nil, cmpTime, req) + } + + return verifyIat(&newNumericDateFromSeconds(iat).Time, cmpTime, req) + case json.Number: + v, _ := iat.Float64() + + return verifyIat(&newNumericDateFromSeconds(v).Time, cmpTime, req) + } + + return false +} + +// VerifyNotBefore compares the nbf claim against cmp (cmp >= nbf). +// If req is false, it will return true, if nbf is unset. +func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool { + cmpTime := time.Unix(cmp, 0) + + v, ok := m["nbf"] + if !ok { + return !req + } + + switch nbf := v.(type) { + case float64: + if nbf == 0 { + return verifyNbf(nil, cmpTime, req) + } + + return verifyNbf(&newNumericDateFromSeconds(nbf).Time, cmpTime, req) + case json.Number: + v, _ := nbf.Float64() + + return verifyNbf(&newNumericDateFromSeconds(v).Time, cmpTime, req) + } + + return false +} + +// VerifyIssuer compares the iss claim against cmp. +// If required is false, this method will return true if the value matches or is unset +func (m MapClaims) VerifyIssuer(cmp string, req bool) bool { + iss, _ := m["iss"].(string) + return verifyIss(iss, cmp, req) +} + +// Valid validates time based claims "exp, iat, nbf". +// There is no accounting for clock skew. +// As well, if any of the above claims are not in the token, it will still +// be considered a valid claim. +func (m MapClaims) Valid() error { + vErr := new(ValidationError) + now := TimeFunc().Unix() + + if !m.VerifyExpiresAt(now, false) { + // TODO(oxisto): this should be replaced with ErrTokenExpired + vErr.Inner = errors.New("Token is expired") + vErr.Errors |= ValidationErrorExpired + } + + if !m.VerifyIssuedAt(now, false) { + // TODO(oxisto): this should be replaced with ErrTokenUsedBeforeIssued + vErr.Inner = errors.New("Token used before issued") + vErr.Errors |= ValidationErrorIssuedAt + } + + if !m.VerifyNotBefore(now, false) { + // TODO(oxisto): this should be replaced with ErrTokenNotValidYet + vErr.Inner = errors.New("Token is not valid yet") + vErr.Errors |= ValidationErrorNotValidYet + } + + if vErr.valid() { + return nil + } + + return vErr +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/none.go b/vendor/github.com/golang-jwt/jwt/v4/none.go new file mode 100644 index 0000000000..f19835d207 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/none.go @@ -0,0 +1,52 @@ +package jwt + +// SigningMethodNone implements the none signing method. This is required by the spec +// but you probably should never use it. +var SigningMethodNone *signingMethodNone + +const UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing method allowed" + +var NoneSignatureTypeDisallowedError error + +type signingMethodNone struct{} +type unsafeNoneMagicConstant string + +func init() { + SigningMethodNone = &signingMethodNone{} + NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid) + + RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod { + return SigningMethodNone + }) +} + +func (m *signingMethodNone) Alg() string { + return "none" +} + +// Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key +func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) { + // Key must be UnsafeAllowNoneSignatureType to prevent accidentally + // accepting 'none' signing method + if _, ok := key.(unsafeNoneMagicConstant); !ok { + return NoneSignatureTypeDisallowedError + } + // If signing method is none, signature must be an empty string + if signature != "" { + return NewValidationError( + "'none' signing method with non-empty signature", + ValidationErrorSignatureInvalid, + ) + } + + // Accept 'none' signing method. + return nil +} + +// Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key +func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) { + if _, ok := key.(unsafeNoneMagicConstant); ok { + return "", nil + } + return "", NoneSignatureTypeDisallowedError +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/parser.go b/vendor/github.com/golang-jwt/jwt/v4/parser.go new file mode 100644 index 0000000000..9dd36e5a5a --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/parser.go @@ -0,0 +1,176 @@ +package jwt + +import ( + "bytes" + "encoding/json" + "fmt" + "strings" +) + +type Parser struct { + // If populated, only these methods will be considered valid. + // + // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. + ValidMethods []string + + // Use JSON Number format in JSON decoder. + // + // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. + UseJSONNumber bool + + // Skip claims validation during token parsing. + // + // Deprecated: In future releases, this field will not be exported anymore and should be set with an option to NewParser instead. + SkipClaimsValidation bool +} + +// NewParser creates a new Parser with the specified options +func NewParser(options ...ParserOption) *Parser { + p := &Parser{} + + // loop through our parsing options and apply them + for _, option := range options { + option(p) + } + + return p +} + +// Parse parses, validates, verifies the signature and returns the parsed token. keyFunc will +// receive the parsed token and should return the key for validating. +func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) { + return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc) +} + +// ParseWithClaims parses, validates, and verifies like Parse, but supplies a default object +// implementing the Claims interface. This provides default values which can be overridden and +// allows a caller to use their own type, rather than the default MapClaims implementation of +// Claims. +// +// Note: If you provide a custom claim implementation that embeds one of the standard claims (such +// as RegisteredClaims), make sure that a) you either embed a non-pointer version of the claims or +// b) if you are using a pointer, allocate the proper memory for it before passing in the overall +// claims, otherwise you might run into a panic. +func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) { + token, parts, err := p.ParseUnverified(tokenString, claims) + if err != nil { + return token, err + } + + // Verify signing method is in the required set + if p.ValidMethods != nil { + var signingMethodValid = false + var alg = token.Method.Alg() + for _, m := range p.ValidMethods { + if m == alg { + signingMethodValid = true + break + } + } + if !signingMethodValid { + // signing method is not in the listed set + return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid) + } + } + + // Lookup key + var key interface{} + if keyFunc == nil { + // keyFunc was not provided. short circuiting validation + return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable) + } + if key, err = keyFunc(token); err != nil { + // keyFunc returned an error + if ve, ok := err.(*ValidationError); ok { + return token, ve + } + return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable} + } + + // Perform validation + token.Signature = parts[2] + if err := token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil { + return token, &ValidationError{Inner: err, Errors: ValidationErrorSignatureInvalid} + } + + vErr := &ValidationError{} + + // Validate Claims + if !p.SkipClaimsValidation { + if err := token.Claims.Valid(); err != nil { + // If the Claims Valid returned an error, check if it is a validation error, + // If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set + if e, ok := err.(*ValidationError); !ok { + vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid} + } else { + vErr = e + } + return token, vErr + } + } + + // No errors so far, token is valid. + token.Valid = true + + return token, nil +} + +// ParseUnverified parses the token but doesn't validate the signature. +// +// WARNING: Don't use this method unless you know what you're doing. +// +// It's only ever useful in cases where you know the signature is valid (because it has +// been checked previously in the stack) and you want to extract values from it. +func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) { + parts = strings.Split(tokenString, ".") + if len(parts) != 3 { + return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed) + } + + token = &Token{Raw: tokenString} + + // parse Header + var headerBytes []byte + if headerBytes, err = DecodeSegment(parts[0]); err != nil { + if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") { + return token, parts, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed) + } + return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} + } + if err = json.Unmarshal(headerBytes, &token.Header); err != nil { + return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} + } + + // parse Claims + var claimBytes []byte + token.Claims = claims + + if claimBytes, err = DecodeSegment(parts[1]); err != nil { + return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} + } + dec := json.NewDecoder(bytes.NewBuffer(claimBytes)) + if p.UseJSONNumber { + dec.UseNumber() + } + // JSON Decode. Special case for map type to avoid weird pointer behavior + if c, ok := token.Claims.(MapClaims); ok { + err = dec.Decode(&c) + } else { + err = dec.Decode(&claims) + } + // Handle decode error + if err != nil { + return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed} + } + + // Lookup signature method + if method, ok := token.Header["alg"].(string); ok { + if token.Method = GetSigningMethod(method); token.Method == nil { + return token, parts, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable) + } + } else { + return token, parts, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable) + } + + return token, parts, nil +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/parser_option.go b/vendor/github.com/golang-jwt/jwt/v4/parser_option.go new file mode 100644 index 0000000000..6ea6f9527d --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/parser_option.go @@ -0,0 +1,29 @@ +package jwt + +// ParserOption is used to implement functional-style options that modify the behavior of the parser. To add +// new options, just create a function (ideally beginning with With or Without) that returns an anonymous function that +// takes a *Parser type as input and manipulates its configuration accordingly. +type ParserOption func(*Parser) + +// WithValidMethods is an option to supply algorithm methods that the parser will check. Only those methods will be considered valid. +// It is heavily encouraged to use this option in order to prevent attacks such as https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/. +func WithValidMethods(methods []string) ParserOption { + return func(p *Parser) { + p.ValidMethods = methods + } +} + +// WithJSONNumber is an option to configure the underlying JSON parser with UseNumber +func WithJSONNumber() ParserOption { + return func(p *Parser) { + p.UseJSONNumber = true + } +} + +// WithoutClaimsValidation is an option to disable claims validation. This option should only be used if you exactly know +// what you are doing. +func WithoutClaimsValidation() ParserOption { + return func(p *Parser) { + p.SkipClaimsValidation = true + } +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa.go b/vendor/github.com/golang-jwt/jwt/v4/rsa.go new file mode 100644 index 0000000000..b910b19c0b --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/rsa.go @@ -0,0 +1,101 @@ +package jwt + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" +) + +// SigningMethodRSA implements the RSA family of signing methods. +// Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation +type SigningMethodRSA struct { + Name string + Hash crypto.Hash +} + +// Specific instances for RS256 and company +var ( + SigningMethodRS256 *SigningMethodRSA + SigningMethodRS384 *SigningMethodRSA + SigningMethodRS512 *SigningMethodRSA +) + +func init() { + // RS256 + SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256} + RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod { + return SigningMethodRS256 + }) + + // RS384 + SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384} + RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod { + return SigningMethodRS384 + }) + + // RS512 + SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512} + RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod { + return SigningMethodRS512 + }) +} + +func (m *SigningMethodRSA) Alg() string { + return m.Name +} + +// Verify implements token verification for the SigningMethod +// For this signing method, must be an *rsa.PublicKey structure. +func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error { + var err error + + // Decode the signature + var sig []byte + if sig, err = DecodeSegment(signature); err != nil { + return err + } + + var rsaKey *rsa.PublicKey + var ok bool + + if rsaKey, ok = key.(*rsa.PublicKey); !ok { + return ErrInvalidKeyType + } + + // Create hasher + if !m.Hash.Available() { + return ErrHashUnavailable + } + hasher := m.Hash.New() + hasher.Write([]byte(signingString)) + + // Verify the signature + return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig) +} + +// Sign implements token signing for the SigningMethod +// For this signing method, must be an *rsa.PrivateKey structure. +func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) { + var rsaKey *rsa.PrivateKey + var ok bool + + // Validate type of key + if rsaKey, ok = key.(*rsa.PrivateKey); !ok { + return "", ErrInvalidKey + } + + // Create the hasher + if !m.Hash.Available() { + return "", ErrHashUnavailable + } + + hasher := m.Hash.New() + hasher.Write([]byte(signingString)) + + // Sign the string and return the encoded bytes + if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil { + return EncodeSegment(sigBytes), nil + } else { + return "", err + } +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go b/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go new file mode 100644 index 0000000000..4fd6f9e610 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/rsa_pss.go @@ -0,0 +1,143 @@ +//go:build go1.4 +// +build go1.4 + +package jwt + +import ( + "crypto" + "crypto/rand" + "crypto/rsa" +) + +// SigningMethodRSAPSS implements the RSAPSS family of signing methods signing methods +type SigningMethodRSAPSS struct { + *SigningMethodRSA + Options *rsa.PSSOptions + // VerifyOptions is optional. If set overrides Options for rsa.VerifyPPS. + // Used to accept tokens signed with rsa.PSSSaltLengthAuto, what doesn't follow + // https://tools.ietf.org/html/rfc7518#section-3.5 but was used previously. + // See https://github.com/dgrijalva/jwt-go/issues/285#issuecomment-437451244 for details. + VerifyOptions *rsa.PSSOptions +} + +// Specific instances for RS/PS and company. +var ( + SigningMethodPS256 *SigningMethodRSAPSS + SigningMethodPS384 *SigningMethodRSAPSS + SigningMethodPS512 *SigningMethodRSAPSS +) + +func init() { + // PS256 + SigningMethodPS256 = &SigningMethodRSAPSS{ + SigningMethodRSA: &SigningMethodRSA{ + Name: "PS256", + Hash: crypto.SHA256, + }, + Options: &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + }, + VerifyOptions: &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthAuto, + }, + } + RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod { + return SigningMethodPS256 + }) + + // PS384 + SigningMethodPS384 = &SigningMethodRSAPSS{ + SigningMethodRSA: &SigningMethodRSA{ + Name: "PS384", + Hash: crypto.SHA384, + }, + Options: &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + }, + VerifyOptions: &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthAuto, + }, + } + RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod { + return SigningMethodPS384 + }) + + // PS512 + SigningMethodPS512 = &SigningMethodRSAPSS{ + SigningMethodRSA: &SigningMethodRSA{ + Name: "PS512", + Hash: crypto.SHA512, + }, + Options: &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthEqualsHash, + }, + VerifyOptions: &rsa.PSSOptions{ + SaltLength: rsa.PSSSaltLengthAuto, + }, + } + RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod { + return SigningMethodPS512 + }) +} + +// Verify implements token verification for the SigningMethod. +// For this verify method, key must be an rsa.PublicKey struct +func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error { + var err error + + // Decode the signature + var sig []byte + if sig, err = DecodeSegment(signature); err != nil { + return err + } + + var rsaKey *rsa.PublicKey + switch k := key.(type) { + case *rsa.PublicKey: + rsaKey = k + default: + return ErrInvalidKey + } + + // Create hasher + if !m.Hash.Available() { + return ErrHashUnavailable + } + hasher := m.Hash.New() + hasher.Write([]byte(signingString)) + + opts := m.Options + if m.VerifyOptions != nil { + opts = m.VerifyOptions + } + + return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, opts) +} + +// Sign implements token signing for the SigningMethod. +// For this signing method, key must be an rsa.PrivateKey struct +func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) { + var rsaKey *rsa.PrivateKey + + switch k := key.(type) { + case *rsa.PrivateKey: + rsaKey = k + default: + return "", ErrInvalidKeyType + } + + // Create the hasher + if !m.Hash.Available() { + return "", ErrHashUnavailable + } + + hasher := m.Hash.New() + hasher.Write([]byte(signingString)) + + // Sign the string and return the encoded bytes + if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil { + return EncodeSegment(sigBytes), nil + } else { + return "", err + } +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go b/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go new file mode 100644 index 0000000000..1966c450bf --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/rsa_utils.go @@ -0,0 +1,105 @@ +package jwt + +import ( + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "errors" +) + +var ( + ErrKeyMustBePEMEncoded = errors.New("invalid key: Key must be a PEM encoded PKCS1 or PKCS8 key") + ErrNotRSAPrivateKey = errors.New("key is not a valid RSA private key") + ErrNotRSAPublicKey = errors.New("key is not a valid RSA public key") +) + +// ParseRSAPrivateKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 private key +func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + var parsedKey interface{} + if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil { + if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil { + return nil, err + } + } + + var pkey *rsa.PrivateKey + var ok bool + if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { + return nil, ErrNotRSAPrivateKey + } + + return pkey, nil +} + +// ParseRSAPrivateKeyFromPEMWithPassword parses a PEM encoded PKCS1 or PKCS8 private key protected with password +// +// Deprecated: This function is deprecated and should not be used anymore. It uses the deprecated x509.DecryptPEMBlock +// function, which was deprecated since RFC 1423 is regarded insecure by design. Unfortunately, there is no alternative +// in the Go standard library for now. See https://github.com/golang/go/issues/8860. +func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + var parsedKey interface{} + + var blockDecrypted []byte + if blockDecrypted, err = x509.DecryptPEMBlock(block, []byte(password)); err != nil { + return nil, err + } + + if parsedKey, err = x509.ParsePKCS1PrivateKey(blockDecrypted); err != nil { + if parsedKey, err = x509.ParsePKCS8PrivateKey(blockDecrypted); err != nil { + return nil, err + } + } + + var pkey *rsa.PrivateKey + var ok bool + if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok { + return nil, ErrNotRSAPrivateKey + } + + return pkey, nil +} + +// ParseRSAPublicKeyFromPEM parses a PEM encoded PKCS1 or PKCS8 public key +func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) { + var err error + + // Parse PEM block + var block *pem.Block + if block, _ = pem.Decode(key); block == nil { + return nil, ErrKeyMustBePEMEncoded + } + + // Parse the key + var parsedKey interface{} + if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil { + if cert, err := x509.ParseCertificate(block.Bytes); err == nil { + parsedKey = cert.PublicKey + } else { + return nil, err + } + } + + var pkey *rsa.PublicKey + var ok bool + if pkey, ok = parsedKey.(*rsa.PublicKey); !ok { + return nil, ErrNotRSAPublicKey + } + + return pkey, nil +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/signing_method.go b/vendor/github.com/golang-jwt/jwt/v4/signing_method.go new file mode 100644 index 0000000000..241ae9c60d --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/signing_method.go @@ -0,0 +1,46 @@ +package jwt + +import ( + "sync" +) + +var signingMethods = map[string]func() SigningMethod{} +var signingMethodLock = new(sync.RWMutex) + +// SigningMethod can be used add new methods for signing or verifying tokens. +type SigningMethod interface { + Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid + Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error + Alg() string // returns the alg identifier for this method (example: 'HS256') +} + +// RegisterSigningMethod registers the "alg" name and a factory function for signing method. +// This is typically done during init() in the method's implementation +func RegisterSigningMethod(alg string, f func() SigningMethod) { + signingMethodLock.Lock() + defer signingMethodLock.Unlock() + + signingMethods[alg] = f +} + +// GetSigningMethod retrieves a signing method from an "alg" string +func GetSigningMethod(alg string) (method SigningMethod) { + signingMethodLock.RLock() + defer signingMethodLock.RUnlock() + + if methodF, ok := signingMethods[alg]; ok { + method = methodF() + } + return +} + +// GetAlgorithms returns a list of registered "alg" names +func GetAlgorithms() (algs []string) { + signingMethodLock.RLock() + defer signingMethodLock.RUnlock() + + for alg := range signingMethods { + algs = append(algs, alg) + } + return +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf b/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf new file mode 100644 index 0000000000..53745d51d7 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/staticcheck.conf @@ -0,0 +1 @@ +checks = ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1023"] diff --git a/vendor/github.com/golang-jwt/jwt/v4/token.go b/vendor/github.com/golang-jwt/jwt/v4/token.go new file mode 100644 index 0000000000..786b275ce0 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/token.go @@ -0,0 +1,143 @@ +package jwt + +import ( + "encoding/base64" + "encoding/json" + "strings" + "time" +) + +// DecodePaddingAllowed will switch the codec used for decoding JWTs respectively. Note that the JWS RFC7515 +// states that the tokens will utilize a Base64url encoding with no padding. Unfortunately, some implementations +// of JWT are producing non-standard tokens, and thus require support for decoding. Note that this is a global +// variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe. +// To use the non-recommended decoding, set this boolean to `true` prior to using this package. +var DecodePaddingAllowed bool + +// DecodeStrict will switch the codec used for decoding JWTs into strict mode. +// In this mode, the decoder requires that trailing padding bits are zero, as described in RFC 4648 section 3.5. +// Note that this is a global variable, and updating it will change the behavior on a package level, and is also NOT go-routine safe. +// To use strict decoding, set this boolean to `true` prior to using this package. +var DecodeStrict bool + +// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time). +// You can override it to use another time value. This is useful for testing or if your +// server uses a different time zone than your tokens. +var TimeFunc = time.Now + +// Keyfunc will be used by the Parse methods as a callback function to supply +// the key for verification. The function receives the parsed, +// but unverified Token. This allows you to use properties in the +// Header of the token (such as `kid`) to identify which key to use. +type Keyfunc func(*Token) (interface{}, error) + +// Token represents a JWT Token. Different fields will be used depending on whether you're +// creating or parsing/verifying a token. +type Token struct { + Raw string // The raw token. Populated when you Parse a token + Method SigningMethod // The signing method used or to be used + Header map[string]interface{} // The first segment of the token + Claims Claims // The second segment of the token + Signature string // The third segment of the token. Populated when you Parse a token + Valid bool // Is the token valid? Populated when you Parse/Verify a token +} + +// New creates a new Token with the specified signing method and an empty map of claims. +func New(method SigningMethod) *Token { + return NewWithClaims(method, MapClaims{}) +} + +// NewWithClaims creates a new Token with the specified signing method and claims. +func NewWithClaims(method SigningMethod, claims Claims) *Token { + return &Token{ + Header: map[string]interface{}{ + "typ": "JWT", + "alg": method.Alg(), + }, + Claims: claims, + Method: method, + } +} + +// SignedString creates and returns a complete, signed JWT. +// The token is signed using the SigningMethod specified in the token. +func (t *Token) SignedString(key interface{}) (string, error) { + var sig, sstr string + var err error + if sstr, err = t.SigningString(); err != nil { + return "", err + } + if sig, err = t.Method.Sign(sstr, key); err != nil { + return "", err + } + return strings.Join([]string{sstr, sig}, "."), nil +} + +// SigningString generates the signing string. This is the +// most expensive part of the whole deal. Unless you +// need this for something special, just go straight for +// the SignedString. +func (t *Token) SigningString() (string, error) { + var err error + var jsonValue []byte + + if jsonValue, err = json.Marshal(t.Header); err != nil { + return "", err + } + header := EncodeSegment(jsonValue) + + if jsonValue, err = json.Marshal(t.Claims); err != nil { + return "", err + } + claim := EncodeSegment(jsonValue) + + return strings.Join([]string{header, claim}, "."), nil +} + +// Parse parses, validates, verifies the signature and returns the parsed token. +// keyFunc will receive the parsed token and should return the cryptographic key +// for verifying the signature. +// The caller is strongly encouraged to set the WithValidMethods option to +// validate the 'alg' claim in the token matches the expected algorithm. +// For more details about the importance of validating the 'alg' claim, +// see https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/ +func Parse(tokenString string, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { + return NewParser(options...).Parse(tokenString, keyFunc) +} + +// ParseWithClaims is a shortcut for NewParser().ParseWithClaims(). +// +// Note: If you provide a custom claim implementation that embeds one of the standard claims (such as RegisteredClaims), +// make sure that a) you either embed a non-pointer version of the claims or b) if you are using a pointer, allocate the +// proper memory for it before passing in the overall claims, otherwise you might run into a panic. +func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc, options ...ParserOption) (*Token, error) { + return NewParser(options...).ParseWithClaims(tokenString, claims, keyFunc) +} + +// EncodeSegment encodes a JWT specific base64url encoding with padding stripped +// +// Deprecated: In a future release, we will demote this function to a non-exported function, since it +// should only be used internally +func EncodeSegment(seg []byte) string { + return base64.RawURLEncoding.EncodeToString(seg) +} + +// DecodeSegment decodes a JWT specific base64url encoding with padding stripped +// +// Deprecated: In a future release, we will demote this function to a non-exported function, since it +// should only be used internally +func DecodeSegment(seg string) ([]byte, error) { + encoding := base64.RawURLEncoding + + if DecodePaddingAllowed { + if l := len(seg) % 4; l > 0 { + seg += strings.Repeat("=", 4-l) + } + encoding = base64.URLEncoding + } + + if DecodeStrict { + encoding = encoding.Strict() + } + return encoding.DecodeString(seg) +} diff --git a/vendor/github.com/golang-jwt/jwt/v4/types.go b/vendor/github.com/golang-jwt/jwt/v4/types.go new file mode 100644 index 0000000000..ac8e140eb1 --- /dev/null +++ b/vendor/github.com/golang-jwt/jwt/v4/types.go @@ -0,0 +1,145 @@ +package jwt + +import ( + "encoding/json" + "fmt" + "math" + "reflect" + "strconv" + "time" +) + +// TimePrecision sets the precision of times and dates within this library. +// This has an influence on the precision of times when comparing expiry or +// other related time fields. Furthermore, it is also the precision of times +// when serializing. +// +// For backwards compatibility the default precision is set to seconds, so that +// no fractional timestamps are generated. +var TimePrecision = time.Second + +// MarshalSingleStringAsArray modifies the behaviour of the ClaimStrings type, especially +// its MarshalJSON function. +// +// If it is set to true (the default), it will always serialize the type as an +// array of strings, even if it just contains one element, defaulting to the behaviour +// of the underlying []string. If it is set to false, it will serialize to a single +// string, if it contains one element. Otherwise, it will serialize to an array of strings. +var MarshalSingleStringAsArray = true + +// NumericDate represents a JSON numeric date value, as referenced at +// https://datatracker.ietf.org/doc/html/rfc7519#section-2. +type NumericDate struct { + time.Time +} + +// NewNumericDate constructs a new *NumericDate from a standard library time.Time struct. +// It will truncate the timestamp according to the precision specified in TimePrecision. +func NewNumericDate(t time.Time) *NumericDate { + return &NumericDate{t.Truncate(TimePrecision)} +} + +// newNumericDateFromSeconds creates a new *NumericDate out of a float64 representing a +// UNIX epoch with the float fraction representing non-integer seconds. +func newNumericDateFromSeconds(f float64) *NumericDate { + round, frac := math.Modf(f) + return NewNumericDate(time.Unix(int64(round), int64(frac*1e9))) +} + +// MarshalJSON is an implementation of the json.RawMessage interface and serializes the UNIX epoch +// represented in NumericDate to a byte array, using the precision specified in TimePrecision. +func (date NumericDate) MarshalJSON() (b []byte, err error) { + var prec int + if TimePrecision < time.Second { + prec = int(math.Log10(float64(time.Second) / float64(TimePrecision))) + } + truncatedDate := date.Truncate(TimePrecision) + + // For very large timestamps, UnixNano would overflow an int64, but this + // function requires nanosecond level precision, so we have to use the + // following technique to get round the issue: + // 1. Take the normal unix timestamp to form the whole number part of the + // output, + // 2. Take the result of the Nanosecond function, which retuns the offset + // within the second of the particular unix time instance, to form the + // decimal part of the output + // 3. Concatenate them to produce the final result + seconds := strconv.FormatInt(truncatedDate.Unix(), 10) + nanosecondsOffset := strconv.FormatFloat(float64(truncatedDate.Nanosecond())/float64(time.Second), 'f', prec, 64) + + output := append([]byte(seconds), []byte(nanosecondsOffset)[1:]...) + + return output, nil +} + +// UnmarshalJSON is an implementation of the json.RawMessage interface and deserializses a +// NumericDate from a JSON representation, i.e. a json.Number. This number represents an UNIX epoch +// with either integer or non-integer seconds. +func (date *NumericDate) UnmarshalJSON(b []byte) (err error) { + var ( + number json.Number + f float64 + ) + + if err = json.Unmarshal(b, &number); err != nil { + return fmt.Errorf("could not parse NumericData: %w", err) + } + + if f, err = number.Float64(); err != nil { + return fmt.Errorf("could not convert json number value to float: %w", err) + } + + n := newNumericDateFromSeconds(f) + *date = *n + + return nil +} + +// ClaimStrings is basically just a slice of strings, but it can be either serialized from a string array or just a string. +// This type is necessary, since the "aud" claim can either be a single string or an array. +type ClaimStrings []string + +func (s *ClaimStrings) UnmarshalJSON(data []byte) (err error) { + var value interface{} + + if err = json.Unmarshal(data, &value); err != nil { + return err + } + + var aud []string + + switch v := value.(type) { + case string: + aud = append(aud, v) + case []string: + aud = ClaimStrings(v) + case []interface{}: + for _, vv := range v { + vs, ok := vv.(string) + if !ok { + return &json.UnsupportedTypeError{Type: reflect.TypeOf(vv)} + } + aud = append(aud, vs) + } + case nil: + return nil + default: + return &json.UnsupportedTypeError{Type: reflect.TypeOf(v)} + } + + *s = aud + + return +} + +func (s ClaimStrings) MarshalJSON() (b []byte, err error) { + // This handles a special case in the JWT RFC. If the string array, e.g. used by the "aud" field, + // only contains one element, it MAY be serialized as a single string. This may or may not be + // desired based on the ecosystem of other JWT library used, so we make it configurable by the + // variable MarshalSingleStringAsArray. + if len(s) == 1 && !MarshalSingleStringAsArray { + return json.Marshal(s[0]) + } + + return json.Marshal([]string(s)) +} diff --git a/vendor/github.com/google/go-github/v45/AUTHORS b/vendor/github.com/google/go-github/v45/AUTHORS new file mode 100644 index 0000000000..80bd26dd4f --- /dev/null +++ b/vendor/github.com/google/go-github/v45/AUTHORS @@ -0,0 +1,357 @@ +# This is the official list of go-github authors for copyright purposes. +# +# This does not necessarily list everyone who has contributed code, since in +# some cases, their employer may be the copyright holder. To see the full list +# of contributors, see the revision history in source control or +# https://github.com/google/go-github/graphs/contributors. +# +# Authors who wish to be recognized in this file should add themselves (or +# their employer, as appropriate). + +178inaba +2BFL +413x +Abhinav Gupta +adrienzieba +afdesk +Ahmed Hagy +Aidan Steele +Ainsley Chong +ajz01 +Akeda Bagus +Akhil Mohan +Alec Thomas +Aleks Clark +Alex Bramley +Alex Orr +Alex Unger +Alexander Harkness +Alexis Gauthiez +Ali Farooq +Allen Sun +Amey Sakhadeo +Anders Janmyr +Andreas Garnæs +Andrew Ryabchun +Andy Grunwald +Andy Hume +Andy Lindeman +angie pinilla +anjanashenoy +Anshuman Bhartiya +Antoine +Antoine Pelisse +Anton Nguyen +Anubha Kushwaha +appilon +aprp +Aravind +Arda Kuyumcu +Arıl Bozoluk +Asier Marruedo +Austin Burdine +Austin Dizzy +Azuka Okuleye +Ben Batha +Benjamen Keroack +Beshr Kayali +Beyang Liu +Billy Keyes +Billy Lynch +Björn Häuser +boljen +Brad Harris +Brad Moylan +Bradley Falzon +Bradley McAllister +Brandon Cook +Brett Logan +Brian Egizi +Bryan Boreham +Cami Diez +Carl Johnson +Carlos Alexandro Becker +Carlos Tadeu Panato Junior +chandresh-pancholi +Charles Fenwick Elliott +Charlie Yan +Chmouel Boudjnah +Chris King +Chris Mc +Chris Raborg +Chris Roche +Chris Schaefer +chrisforrette +Christian Muehlhaeuser +Christoph Sassenberg +Colin Misare +Craig Peterson +Cristian Maglie +Daehyeok Mun +Daniel Lanner +Daniel Leavitt +Daniel Nilsson +Daoq +Dave Du Cros +Dave Henderson +Dave Perrett +Dave Protasowski +David Deng +David J. M. Karlsen +David Jannotta +David Ji +David Lopez Reyes +Davide Zipeto +Dennis Webb +Derek Jobst +Dhi Aurrahman +Diego Lapiduz +Dmitri Shuralyov +dmnlk +Don Petersen +Doug Turner +Drew Fradette +Dustin Deus +Eivind +Eli Uriegas +Elliott Beach +Emerson Wood +eperm +Erick Fejta +Erik Nobel +erwinvaneyk +Evan Elias +Fabian Holler +Fabrice +Felix Geisendörfer +Filippo Valsorda +Florian Forster +Francesc Gil +Francis +Francisco Guimarães +Fredrik Jönsson +Garrett Squire +George Kontridze +Georgy Buranov +Glen Mailer +Gnahz +Google Inc. +Grachev Mikhail +griffin_stewie +Guillaume Jacquet +Guz Alexander +Guðmundur Bjarni Ólafsson +Hanno Hecker +Hari haran +haya14busa +haya14busa +Huy Tr +huydx +i2bskn +Ikko Ashimine +Ioannis Georgoulas +Isao Jonas +ishan upadhyay +isqua +Jacob Valdemar +Jake Krammer +Jake White +Jameel Haffejee +James Cockbain +James Loh +Jan Kosecki +Jan Švábík +Javier Campanini +Jef LeCompte +Jens Rantil +Jeremy Morris +Jesse Haka +Jesse Newland +Jihoon Chung +Jimmi Dyson +Joan Saum +Joe Tsai +John Barton +John Engelman +John Liu +Jordan Brockopp +Jordan Sussman +Joshua Bezaleel Abednego +JP Phillips +jpbelanger-mtl +Juan +Juan Basso +Julien Garcia Gonzalez +Julien Rostand +Junya Kono +Justin Abrahms +Jusung Lee +jzhoucliqr +kadern0 +Katrina Owen +Kautilya Tripathi +Keita Urashima +Kevin Burke +Kirill +Konrad Malawski +Kookheon Kwon +Krzysztof Kowalczyk +Kshitij Saraogi +Kumar Saurabh +kyokomi +Laurent Verdoïa +Liam Galvin +Lovro Mažgon +Luca Campese +Lucas Alcantara +Luke Evers +Luke Kysow +Luke Roberts +Luke Young +lynn [they] +Maksim Zhylinski +Marc Binder +Marcelo Carlos +Mark Tareshawty +Martin Holman +Martin-Louis Bright +Martins Sipenko +Marwan Sulaiman +Masayuki Izumi +Mat Geist +Matin Rahmanian +Matt +Matt Brender +Matt Gaunt +Matt Landis +Matt Moore +Maxime Bury +Michael Spiegel +Michael Tiller +Michał Glapa +Michelangelo Morrillo +Mukundan Senthil +Munia Balayil +Nadav Kaner +Nathan VanBenschoten +Navaneeth Suresh +Neil O'Toole +Nick Miyake +Nick Platt +Nick Spragg +Nikhita Raghunath +Nilesh Singh +Noah Zoschke +ns-cweber +Ole Orhagen +Oleg Kovalov +Ondřej Kupka +Ori Talmor +Pablo Pérez Schröder +Palash Nigam +Panagiotis Moustafellos +Parham Alvani +Parker Moore +parkhyukjun89 +Patrick DeVivo +Patrick Marabeas +Pavel Shtanko +Pete Wagner +Petr Shevtsov +Pierre Carrier +Piotr Zurek +Piyush Chugh +Pratik Mallya +Qais Patankar +Quang Le Hong +Quentin Leffray +Quinn Slack +Rackspace US, Inc. +Radek Simko +Radliński Ignacy +Rajat Jindal +Rajendra arora +Ranbir Singh +Ravi Shekhar Jethani +RaviTeja Pothana +rc1140 +Red Hat, Inc. +Reetuparna Mukherjee +Reinier Timmer +Renjith R +Ricco Førgaard +Rob Figueiredo +Rohit Upadhyay +Ronak Jain +Ross Gustafson +Ruben Vereecken +Russell Boley +Ryan Leung +Ryan Lower +Ryo Nakao +Saaarah +Safwan Olaimat +Sahil Dua +saisi +Sam Minnée +Sandeep Sukhani +Sander Knape +Sander van Harmelen +Sanket Payghan +Sarasa Kisaragi +Sean Wang +Sebastian Mandrean +Sebastian Mæland Pedersen +Sergey Romanov +Sergio Garcia +Seth Vargo +Sevki +Shagun Khemka +shakeelrao +Shawn Catanzarite +Shawn Smith +Shibasis Patel +Shrikrishna Singh +Simon Davis +sona-tar +SoundCloud, Ltd. +Sridhar Mocherla +SriVignessh Pss +Stefan Sedich +Steve Teuber +Stian Eikeland +Suhaib Mujahid +Szymon Kodrebski +Søren Hansen +Takayuki Watanabe +Taketoshi Fujiwara +Taketoshi Fujiwara +Tasya Aditya Rukmana +Theo Henson +Thomas Aidan Curran +Thomas Bruyelle +Timothée Peignier +tkhandel +Trey Tacon +ttacon +Vaibhav Singh +Varadarajan Aravamudhan +Victor Castell +Victor Vrantchan +vikkyomkar +Vlad Ungureanu +Wasim Thabraze +Weslei Juan Moser Pereira +Will Maier +Willem D'Haeseleer +William Bailey +William Cooke +xibz +Yann Malet +Yannick Utard +Yicheng Qin +Yosuke Akatsuka +Yumikiyo Osanai +Yusuke Kuoka +Zach Latta +zhouhaibing089 \ No newline at end of file diff --git a/vendor/github.com/yosida95/uritemplate/v3/LICENSE b/vendor/github.com/google/go-github/v45/LICENSE similarity index 52% rename from vendor/github.com/yosida95/uritemplate/v3/LICENSE rename to vendor/github.com/google/go-github/v45/LICENSE index 79e8f87572..28b6486f0b 100644 --- a/vendor/github.com/yosida95/uritemplate/v3/LICENSE +++ b/vendor/github.com/google/go-github/v45/LICENSE @@ -1,22 +1,24 @@ -Copyright (C) 2016, Kohei YOSHIDA . All rights reserved. +Copyright (c) 2013 The go-github AUTHORS. All rights reserved. Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: +modification, are permitted provided that the following conditions are +met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY diff --git a/vendor/github.com/google/go-github/v45/github/actions.go b/vendor/github.com/google/go-github/v45/github/actions.go new file mode 100644 index 0000000000..8d552f2d0d --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/actions.go @@ -0,0 +1,12 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// ActionsService handles communication with the actions related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/ +type ActionsService service diff --git a/vendor/github.com/google/go-github/v45/github/actions_artifacts.go b/vendor/github.com/google/go-github/v45/github/actions_artifacts.go new file mode 100644 index 0000000000..3b9c83c490 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/actions_artifacts.go @@ -0,0 +1,139 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// Artifact reprents a GitHub artifact. Artifacts allow sharing +// data between jobs in a workflow and provide storage for data +// once a workflow is complete. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/artifacts +type Artifact struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + SizeInBytes *int64 `json:"size_in_bytes,omitempty"` + ArchiveDownloadURL *string `json:"archive_download_url,omitempty"` + Expired *bool `json:"expired,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} + +// ArtifactList represents a list of GitHub artifacts. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/artifacts#artifacts +type ArtifactList struct { + TotalCount *int64 `json:"total_count,omitempty"` + Artifacts []*Artifact `json:"artifacts,omitempty"` +} + +// ListArtifacts lists all artifacts that belong to a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/artifacts#list-artifacts-for-a-repository +func (s *ActionsService) ListArtifacts(ctx context.Context, owner, repo string, opts *ListOptions) (*ArtifactList, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifactList := new(ArtifactList) + resp, err := s.client.Do(ctx, req, artifactList) + if err != nil { + return nil, resp, err + } + + return artifactList, resp, nil +} + +// ListWorkflowRunArtifacts lists all artifacts that belong to a workflow run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/artifacts#list-workflow-run-artifacts +func (s *ActionsService) ListWorkflowRunArtifacts(ctx context.Context, owner, repo string, runID int64, opts *ListOptions) (*ArtifactList, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/artifacts", owner, repo, runID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifactList := new(ArtifactList) + resp, err := s.client.Do(ctx, req, artifactList) + if err != nil { + return nil, resp, err + } + + return artifactList, resp, nil +} + +// GetArtifact gets a specific artifact for a workflow run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/artifacts#get-an-artifact +func (s *ActionsService) GetArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Artifact, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + artifact := new(Artifact) + resp, err := s.client.Do(ctx, req, artifact) + if err != nil { + return nil, resp, err + } + + return artifact, resp, nil +} + +// DownloadArtifact gets a redirect URL to download an archive for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/artifacts#download-an-artifact +func (s *ActionsService) DownloadArtifact(ctx context.Context, owner, repo string, artifactID int64, followRedirects bool) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v/zip", owner, repo, artifactID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, followRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), nil +} + +// DeleteArtifact deletes a workflow run artifact. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/artifacts#delete-an-artifact +func (s *ActionsService) DeleteArtifact(ctx context.Context, owner, repo string, artifactID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/artifacts/%v", owner, repo, artifactID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/actions_runner_groups.go b/vendor/github.com/google/go-github/v45/github/actions_runner_groups.go new file mode 100644 index 0000000000..6d89249150 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/actions_runner_groups.go @@ -0,0 +1,302 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RunnerGroup represents a self-hosted runner group configured in an organization. +type RunnerGroup struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Default *bool `json:"default,omitempty"` + SelectedRepositoriesURL *string `json:"selected_repositories_url,omitempty"` + RunnersURL *string `json:"runners_url,omitempty"` + Inherited *bool `json:"inherited,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` +} + +// RunnerGroups represents a collection of self-hosted runner groups configured for an organization. +type RunnerGroups struct { + TotalCount int `json:"total_count"` + RunnerGroups []*RunnerGroup `json:"runner_groups"` +} + +// CreateRunnerGroupRequest represents a request to create a Runner group for an organization. +type CreateRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + // List of repository IDs that can access the runner group. + SelectedRepositoryIDs []int64 `json:"selected_repository_ids,omitempty"` + // Runners represent a list of runner IDs to add to the runner group. + Runners []int64 `json:"runners,omitempty"` + // If set to True, public repos can use this runner group + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` +} + +// UpdateRunnerGroupRequest represents a request to update a Runner group for an organization. +type UpdateRunnerGroupRequest struct { + Name *string `json:"name,omitempty"` + Visibility *string `json:"visibility,omitempty"` + AllowsPublicRepositories *bool `json:"allows_public_repositories,omitempty"` +} + +// SetRepoAccessRunnerGroupRequest represents a request to replace the list of repositories +// that can access a self-hosted runner group configured in an organization. +type SetRepoAccessRunnerGroupRequest struct { + // Updated list of repository IDs that should be given access to the runner group. + SelectedRepositoryIDs []int64 `json:"selected_repository_ids"` +} + +// SetRunnerGroupRunnersRequest represents a request to replace the list of +// self-hosted runners that are part of an organization runner group. +type SetRunnerGroupRunnersRequest struct { + // Updated list of runner IDs that should be given access to the runner group. + Runners []int64 `json:"runners"` +} + +// ListOrgRunnerGroupOptions extend ListOptions to have the optional parameters VisibleToRepository. +type ListOrgRunnerGroupOptions struct { + ListOptions + + // Only return runner groups that are allowed to be used by this repository. + VisibleToRepository string `url:"visible_to_repository,omitempty"` +} + +// ListOrganizationRunnerGroups lists all self-hosted runner groups configured in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#list-self-hosted-runner-groups-for-an-organization +func (s *ActionsService) ListOrganizationRunnerGroups(ctx context.Context, org string, opts *ListOrgRunnerGroupOptions) (*RunnerGroups, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := &RunnerGroups{} + resp, err := s.client.Do(ctx, req, &groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// GetOrganizationRunnerGroup gets a specific self-hosted runner group for an organization using its RunnerGroup ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#get-a-self-hosted-runner-group-for-an-organization +func (s *ActionsService) GetOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// DeleteOrganizationRunnerGroup deletes a self-hosted runner group from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#delete-a-self-hosted-runner-group-from-an-organization +func (s *ActionsService) DeleteOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrganizationRunnerGroup creates a new self-hosted runner group for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#create-a-self-hosted-runner-group-for-an-organization +func (s *ActionsService) CreateOrganizationRunnerGroup(ctx context.Context, org string, createReq CreateRunnerGroupRequest) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups", org) + req, err := s.client.NewRequest("POST", u, createReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// UpdateOrganizationRunnerGroup updates a self-hosted runner group for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#update-a-self-hosted-runner-group-for-an-organization +func (s *ActionsService) UpdateOrganizationRunnerGroup(ctx context.Context, org string, groupID int64, updateReq UpdateRunnerGroupRequest) (*RunnerGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v", org, groupID) + req, err := s.client.NewRequest("PATCH", u, updateReq) + if err != nil { + return nil, nil, err + } + + runnerGroup := new(RunnerGroup) + resp, err := s.client.Do(ctx, req, runnerGroup) + if err != nil { + return nil, resp, err + } + + return runnerGroup, resp, nil +} + +// ListRepositoryAccessRunnerGroup lists the repositories with access to a self-hosted runner group configured in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#list-repository-access-to-a-self-hosted-runner-group-in-an-organization +func (s *ActionsService) ListRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, opts *ListOptions) (*ListRepositories, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories", org, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repos := &ListRepositories{} + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// SetRepositoryAccessRunnerGroup replaces the list of repositories that have access to a self-hosted runner group configured in an organization +// with a new List of repositories. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#set-repository-access-for-a-self-hosted-runner-group-in-an-organization +func (s *ActionsService) SetRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, ids SetRepoAccessRunnerGroupRequest) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories", org, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRepositoryAccessRunnerGroup adds a repository to the list of selected repositories that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#add-repository-access-to-a-self-hosted-runner-group-in-an-organization +func (s *ActionsService) AddRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID, repoID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories/%v", org, groupID, repoID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveRepositoryAccessRunnerGroup removes a repository from the list of selected repositories that can access a self-hosted runner group. +// The runner group must have visibility set to 'selected'. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#remove-repository-access-to-a-self-hosted-runner-group-in-an-organization +func (s *ActionsService) RemoveRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID, repoID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/repositories/%v", org, groupID, repoID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListRunnerGroupRunners lists self-hosted runners that are in a specific organization group. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#list-self-hosted-runners-in-a-group-for-an-organization +func (s *ActionsService) ListRunnerGroupRunners(ctx context.Context, org string, groupID int64, opts *ListOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners", org, groupID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// SetRunnerGroupRunners replaces the list of self-hosted runners that are part of an organization runner group +// with a new list of runners. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#set-self-hosted-runners-in-a-group-for-an-organization +func (s *ActionsService) SetRunnerGroupRunners(ctx context.Context, org string, groupID int64, ids SetRunnerGroupRunnersRequest) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners", org, groupID) + + req, err := s.client.NewRequest("PUT", u, ids) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddRunnerGroupRunners adds a self-hosted runner to a runner group configured in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#add-a-self-hosted-runner-to-a-group-for-an-organization +func (s *ActionsService) AddRunnerGroupRunners(ctx context.Context, org string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners/%v", org, groupID, runnerID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveRunnerGroupRunners removes a self-hosted runner from a group configured in an organization. +// The runner is then returned to the default group. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runner-groups#remove-a-self-hosted-runner-from-a-group-for-an-organization +func (s *ActionsService) RemoveRunnerGroupRunners(ctx context.Context, org string, groupID, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runner-groups/%v/runners/%v", org, groupID, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/actions_runners.go b/vendor/github.com/google/go-github/v45/github/actions_runners.go new file mode 100644 index 0000000000..40c6be3a92 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/actions_runners.go @@ -0,0 +1,377 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RunnerApplicationDownload represents a binary for the self-hosted runner application that can be downloaded. +type RunnerApplicationDownload struct { + OS *string `json:"os,omitempty"` + Architecture *string `json:"architecture,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` + Filename *string `json:"filename,omitempty"` + TempDownloadToken *string `json:"temp_download_token,omitempty"` + SHA256Checksum *string `json:"sha256_checksum,omitempty"` +} + +// ActionsEnabledOnOrgRepos represents all the repositories in an organization for which Actions is enabled. +type ActionsEnabledOnOrgRepos struct { + TotalCount int `json:"total_count"` + Repositories []*Repository `json:"repositories"` +} + +// ListRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#list-runner-applications-for-a-repository +func (s *ActionsService) ListRunnerApplicationDownloads(ctx context.Context, owner, repo string) ([]*RunnerApplicationDownload, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/downloads", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rads []*RunnerApplicationDownload + resp, err := s.client.Do(ctx, req, &rads) + if err != nil { + return nil, resp, err + } + + return rads, resp, nil +} + +// RegistrationToken represents a token that can be used to add a self-hosted runner to a repository. +type RegistrationToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} + +// CreateRegistrationToken creates a token that can be used to add a self-hosted runner. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#create-a-registration-token-for-a-repository +func (s *ActionsService) CreateRegistrationToken(ctx context.Context, owner, repo string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/registration-token", owner, repo) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// Runner represents a self-hosted runner registered with a repository. +type Runner struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + OS *string `json:"os,omitempty"` + Status *string `json:"status,omitempty"` + Busy *bool `json:"busy,omitempty"` + Labels []*RunnerLabels `json:"labels,omitempty"` +} + +// RunnerLabels represents a collection of labels attached to each runner. +type RunnerLabels struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Runners represents a collection of self-hosted runners for a repository. +type Runners struct { + TotalCount int `json:"total_count"` + Runners []*Runner `json:"runners"` +} + +// ListRunners lists all the self-hosted runners for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#list-self-hosted-runners-for-a-repository +func (s *ActionsService) ListRunners(ctx context.Context, owner, repo string, opts *ListOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// GetRunner gets a specific self-hosted runner for a repository using its runner ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-a-repository +func (s *ActionsService) GetRunner(ctx context.Context, owner, repo string, runnerID int64) (*Runner, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/%v", owner, repo, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runner := new(Runner) + resp, err := s.client.Do(ctx, req, runner) + if err != nil { + return nil, resp, err + } + + return runner, resp, nil +} + +// RemoveToken represents a token that can be used to remove a self-hosted runner from a repository. +type RemoveToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} + +// CreateRemoveToken creates a token that can be used to remove a self-hosted runner from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#create-a-remove-token-for-a-repository +func (s *ActionsService) CreateRemoveToken(ctx context.Context, owner, repo string) (*RemoveToken, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/remove-token", owner, repo) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + removeToken := new(RemoveToken) + resp, err := s.client.Do(ctx, req, removeToken) + if err != nil { + return nil, resp, err + } + + return removeToken, resp, nil +} + +// RemoveRunner forces the removal of a self-hosted runner in a repository using the runner id. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-a-repository +func (s *ActionsService) RemoveRunner(ctx context.Context, owner, repo string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runners/%v", owner, repo, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListOrganizationRunnerApplicationDownloads lists self-hosted runner application binaries that can be downloaded and run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#list-runner-applications-for-an-organization +func (s *ActionsService) ListOrganizationRunnerApplicationDownloads(ctx context.Context, owner string) ([]*RunnerApplicationDownload, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/downloads", owner) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rads []*RunnerApplicationDownload + resp, err := s.client.Do(ctx, req, &rads) + if err != nil { + return nil, resp, err + } + + return rads, resp, nil +} + +// CreateOrganizationRegistrationToken creates a token that can be used to add a self-hosted runner to an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#create-a-registration-token-for-an-organization +func (s *ActionsService) CreateOrganizationRegistrationToken(ctx context.Context, owner string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/registration-token", owner) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// ListOrganizationRunners lists all the self-hosted runners for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#list-self-hosted-runners-for-an-organization +func (s *ActionsService) ListOrganizationRunners(ctx context.Context, owner string, opts *ListOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners", owner) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// ListEnabledReposInOrg lists the selected repositories that are enabled for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#list-selected-repositories-enabled-for-github-actions-in-an-organization +func (s *ActionsService) ListEnabledReposInOrg(ctx context.Context, owner string, opts *ListOptions) (*ActionsEnabledOnOrgRepos, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories", owner) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repos := &ActionsEnabledOnOrgRepos{} + resp, err := s.client.Do(ctx, req, repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// SetEnabledReposInOrg replaces the list of selected repositories that are enabled for GitHub Actions in an organization.. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#set-selected-repositories-enabled-for-github-actions-in-an-organization +func (s *ActionsService) SetEnabledReposInOrg(ctx context.Context, owner string, repositoryIDs []int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories", owner) + + req, err := s.client.NewRequest("PUT", u, struct { + IDs []int64 `json:"selected_repository_ids"` + }{IDs: repositoryIDs}) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// AddEnabledReposInOrg adds a repository to the list of selected repositories that are enabled for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#enable-a-selected-repository-for-github-actions-in-an-organization +func (s *ActionsService) AddEnabledReposInOrg(ctx context.Context, owner string, repositoryID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories/%v", owner, repositoryID) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// RemoveEnabledRepoInOrg removes a single repository from the list of enabled repos for GitHub Actions in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#disable-a-selected-repository-for-github-actions-in-an-organization +func (s *ActionsService) RemoveEnabledRepoInOrg(ctx context.Context, owner string, repositoryID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/repositories/%v", owner, repositoryID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// GetOrganizationRunner gets a specific self-hosted runner for an organization using its runner ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#get-a-self-hosted-runner-for-an-organization +func (s *ActionsService) GetOrganizationRunner(ctx context.Context, owner string, runnerID int64) (*Runner, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/%v", owner, runnerID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runner := new(Runner) + resp, err := s.client.Do(ctx, req, runner) + if err != nil { + return nil, resp, err + } + + return runner, resp, nil +} + +// CreateOrganizationRemoveToken creates a token that can be used to remove a self-hosted runner from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#create-a-remove-token-for-an-organization +func (s *ActionsService) CreateOrganizationRemoveToken(ctx context.Context, owner string) (*RemoveToken, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/remove-token", owner) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + removeToken := new(RemoveToken) + resp, err := s.client.Do(ctx, req, removeToken) + if err != nil { + return nil, resp, err + } + + return removeToken, resp, nil +} + +// RemoveOrganizationRunner forces the removal of a self-hosted runner from an organization using the runner id. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-an-organization +func (s *ActionsService) RemoveOrganizationRunner(ctx context.Context, owner string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/actions/runners/%v", owner, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/actions_secrets.go b/vendor/github.com/google/go-github/v45/github/actions_secrets.go new file mode 100644 index 0000000000..dc057edba2 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/actions_secrets.go @@ -0,0 +1,358 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "strconv" +) + +// PublicKey represents the public key that should be used to encrypt secrets. +type PublicKey struct { + KeyID *string `json:"key_id"` + Key *string `json:"key"` +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This ensures GitHub Enterprise versions which return a numeric key id +// do not error out when unmarshaling. +func (p *PublicKey) UnmarshalJSON(data []byte) error { + var pk struct { + KeyID interface{} `json:"key_id,string"` + Key *string `json:"key"` + } + + if err := json.Unmarshal(data, &pk); err != nil { + return err + } + + p.Key = pk.Key + + switch v := pk.KeyID.(type) { + case nil: + return nil + case string: + p.KeyID = &v + case float64: + p.KeyID = String(strconv.FormatFloat(v, 'f', -1, 64)) + default: + return fmt.Errorf("unable to unmarshal %T as a string", v) + } + + return nil +} + +func (s *ActionsService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + pubKey := new(PublicKey) + resp, err := s.client.Do(ctx, req, pubKey) + if err != nil { + return nil, resp, err + } + + return pubKey, resp, nil +} + +// GetRepoPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-a-repository-public-key +func (s *ActionsService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/public-key", owner, repo) + return s.getPublicKey(ctx, url) +} + +// GetOrgPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-an-organization-public-key +func (s *ActionsService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/public-key", org) + return s.getPublicKey(ctx, url) +} + +// GetEnvPublicKey gets a public key that should be used for secret encryption. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-an-environment-public-key +func (s *ActionsService) GetEnvPublicKey(ctx context.Context, repoID int, env string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/public-key", repoID, env) + return s.getPublicKey(ctx, url) +} + +// Secret represents a repository action secret. +type Secret struct { + Name string `json:"name"` + CreatedAt Timestamp `json:"created_at"` + UpdatedAt Timestamp `json:"updated_at"` + Visibility string `json:"visibility,omitempty"` + SelectedRepositoriesURL string `json:"selected_repositories_url,omitempty"` +} + +// Secrets represents one item from the ListSecrets response. +type Secrets struct { + TotalCount int `json:"total_count"` + Secrets []*Secret `json:"secrets"` +} + +func (s *ActionsService) listSecrets(ctx context.Context, url string, opts *ListOptions) (*Secrets, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + secrets := new(Secrets) + resp, err := s.client.Do(ctx, req, &secrets) + if err != nil { + return nil, resp, err + } + + return secrets, resp, nil +} + +// ListRepoSecrets lists all secrets available in a repository +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#list-repository-secrets +func (s *ActionsService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets", owner, repo) + return s.listSecrets(ctx, url, opts) +} + +// ListOrgSecrets lists all secrets available in an organization +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#list-organization-secrets +func (s *ActionsService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets", org) + return s.listSecrets(ctx, url, opts) +} + +// ListEnvSecrets lists all secrets available in an environment. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#list-environment-secrets +func (s *ActionsService) ListEnvSecrets(ctx context.Context, repoID int, env string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets", repoID, env) + return s.listSecrets(ctx, url, opts) +} + +func (s *ActionsService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + secret := new(Secret) + resp, err := s.client.Do(ctx, req, secret) + if err != nil { + return nil, resp, err + } + + return secret, resp, nil +} + +// GetRepoSecret gets a single repository secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-a-repository-secret +func (s *ActionsService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) + return s.getSecret(ctx, url) +} + +// GetOrgSecret gets a single organization secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-an-organization-secret +func (s *ActionsService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) + return s.getSecret(ctx, url) +} + +// GetEnvSecret gets a single environment secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#get-an-environment-secret +func (s *ActionsService) GetEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Secret, *Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) + return s.getSecret(ctx, url) +} + +// SelectedRepoIDs are the repository IDs that have access to the secret. +type SelectedRepoIDs []int64 + +// EncryptedSecret represents a secret that is encrypted using a public key. +// +// The value of EncryptedValue must be your secret, encrypted with +// LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) +// using the public key retrieved using the GetPublicKey method. +type EncryptedSecret struct { + Name string `json:"-"` + KeyID string `json:"key_id"` + EncryptedValue string `json:"encrypted_value"` + Visibility string `json:"visibility,omitempty"` + SelectedRepositoryIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"` +} + +func (s *ActionsService) putSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, eSecret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrUpdateRepoSecret creates or updates a repository secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#create-or-update-a-repository-secret +func (s *ActionsService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateOrgSecret creates or updates an organization secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#create-or-update-an-organization-secret +func (s *ActionsService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateEnvSecret creates or updates a single environment secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#create-or-update-an-environment-secret +func (s *ActionsService) CreateOrUpdateEnvSecret(ctx context.Context, repoID int, env string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +func (s *ActionsService) deleteSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteRepoSecret deletes a secret in a repository using the secret name. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#delete-a-repository-secret +func (s *ActionsService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) + return s.deleteSecret(ctx, url) +} + +// DeleteOrgSecret deletes a secret in an organization using the secret name. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#delete-an-organization-secret +func (s *ActionsService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) + return s.deleteSecret(ctx, url) +} + +// DeleteEnvSecret deletes a secret in an environment using the secret name. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#delete-an-environment-secret +func (s *ActionsService) DeleteEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Response, error) { + url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) + return s.deleteSecret(ctx, url) +} + +// SelectedReposList represents the list of repositories selected for an organization secret. +type SelectedReposList struct { + TotalCount *int `json:"total_count,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +func (s *ActionsService) listSelectedReposForSecret(ctx context.Context, url string, opts *ListOptions) (*SelectedReposList, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(SelectedReposList) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// ListSelectedReposForOrgSecret lists all repositories that have access to a secret. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#list-selected-repositories-for-an-organization-secret +func (s *ActionsService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) + return s.listSelectedReposForSecret(ctx, url, opts) +} + +func (s *ActionsService) setSelectedReposForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// SetSelectedReposForOrgSecret sets the repositories that have access to a secret. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#set-selected-repositories-for-an-organization-secret +func (s *ActionsService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) + return s.setSelectedReposForSecret(ctx, url, ids) +} + +func (s *ActionsService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddSelectedRepoToOrgSecret adds a repository to an organization secret. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#add-selected-repository-to-an-organization-secret +func (s *ActionsService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.addSelectedRepoToSecret(ctx, url) +} + +func (s *ActionsService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSelectedRepoFromOrgSecret removes a repository from an organization secret. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/secrets#remove-selected-repository-from-an-organization-secret +func (s *ActionsService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) + return s.removeSelectedRepoFromSecret(ctx, url) +} diff --git a/vendor/github.com/google/go-github/v45/github/actions_workflow_jobs.go b/vendor/github.com/google/go-github/v45/github/actions_workflow_jobs.go new file mode 100644 index 0000000000..2867e82af0 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/actions_workflow_jobs.go @@ -0,0 +1,129 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// TaskStep represents a single task step from a sequence of tasks of a job. +type TaskStep struct { + Name *string `json:"name,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + Number *int64 `json:"number,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` +} + +// WorkflowJob represents a repository action workflow job. +type WorkflowJob struct { + ID *int64 `json:"id,omitempty"` + RunID *int64 `json:"run_id,omitempty"` + RunURL *string `json:"run_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` + Name *string `json:"name,omitempty"` + Steps []*TaskStep `json:"steps,omitempty"` + CheckRunURL *string `json:"check_run_url,omitempty"` + // Labels represents runner labels from the `runs-on:` key from a GitHub Actions workflow. + Labels []string `json:"labels,omitempty"` + RunnerID *int64 `json:"runner_id,omitempty"` + RunnerName *string `json:"runner_name,omitempty"` + RunnerGroupID *int64 `json:"runner_group_id,omitempty"` + RunnerGroupName *string `json:"runner_group_name,omitempty"` +} + +// Jobs represents a slice of repository action workflow job. +type Jobs struct { + TotalCount *int `json:"total_count,omitempty"` + Jobs []*WorkflowJob `json:"jobs,omitempty"` +} + +// ListWorkflowJobsOptions specifies optional parameters to ListWorkflowJobs. +type ListWorkflowJobsOptions struct { + // Filter specifies how jobs should be filtered by their completed_at timestamp. + // Possible values are: + // latest - Returns jobs from the most recent execution of the workflow run + // all - Returns all jobs for a workflow run, including from old executions of the workflow run + // + // Default value is "latest". + Filter string `url:"filter,omitempty"` + ListOptions +} + +// ListWorkflowJobs lists all jobs for a workflow run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-jobs#list-jobs-for-a-workflow-run +func (s *ActionsService) ListWorkflowJobs(ctx context.Context, owner, repo string, runID int64, opts *ListWorkflowJobsOptions) (*Jobs, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/runs/%v/jobs", owner, repo, runID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + jobs := new(Jobs) + resp, err := s.client.Do(ctx, req, &jobs) + if err != nil { + return nil, resp, err + } + + return jobs, resp, nil +} + +// GetWorkflowJobByID gets a specific job in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-jobs#get-a-job-for-a-workflow-run +func (s *ActionsService) GetWorkflowJobByID(ctx context.Context, owner, repo string, jobID int64) (*WorkflowJob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v", owner, repo, jobID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + job := new(WorkflowJob) + resp, err := s.client.Do(ctx, req, job) + if err != nil { + return nil, resp, err + } + + return job, resp, nil +} + +// GetWorkflowJobLogs gets a redirect URL to download a plain text file of logs for a workflow job. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-jobs#download-job-logs-for-a-workflow-run +func (s *ActionsService) GetWorkflowJobLogs(ctx context.Context, owner, repo string, jobID int64, followRedirects bool) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/logs", owner, repo, jobID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, followRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} diff --git a/vendor/github.com/google/go-github/v45/github/actions_workflow_runs.go b/vendor/github.com/google/go-github/v45/github/actions_workflow_runs.go new file mode 100644 index 0000000000..de1e6c277a --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/actions_workflow_runs.go @@ -0,0 +1,322 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "net/url" +) + +// WorkflowRun represents a repository action workflow run. +type WorkflowRun struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + RunNumber *int `json:"run_number,omitempty"` + RunAttempt *int `json:"run_attempt,omitempty"` + Event *string `json:"event,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + WorkflowID *int64 `json:"workflow_id,omitempty"` + CheckSuiteID *int64 `json:"check_suite_id,omitempty"` + CheckSuiteNodeID *string `json:"check_suite_node_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + RunStartedAt *Timestamp `json:"run_started_at,omitempty"` + JobsURL *string `json:"jobs_url,omitempty"` + LogsURL *string `json:"logs_url,omitempty"` + CheckSuiteURL *string `json:"check_suite_url,omitempty"` + ArtifactsURL *string `json:"artifacts_url,omitempty"` + CancelURL *string `json:"cancel_url,omitempty"` + RerunURL *string `json:"rerun_url,omitempty"` + PreviousAttemptURL *string `json:"previous_attempt_url,omitempty"` + HeadCommit *HeadCommit `json:"head_commit,omitempty"` + WorkflowURL *string `json:"workflow_url,omitempty"` + Repository *Repository `json:"repository,omitempty"` + HeadRepository *Repository `json:"head_repository,omitempty"` +} + +// WorkflowRuns represents a slice of repository action workflow run. +type WorkflowRuns struct { + TotalCount *int `json:"total_count,omitempty"` + WorkflowRuns []*WorkflowRun `json:"workflow_runs,omitempty"` +} + +// ListWorkflowRunsOptions specifies optional parameters to ListWorkflowRuns. +type ListWorkflowRunsOptions struct { + Actor string `url:"actor,omitempty"` + Branch string `url:"branch,omitempty"` + Event string `url:"event,omitempty"` + Status string `url:"status,omitempty"` + Created string `url:"created,omitempty"` + ListOptions +} + +// WorkflowRunUsage represents a usage of a specific workflow run. +type WorkflowRunUsage struct { + Billable *WorkflowRunEnvironment `json:"billable,omitempty"` + RunDurationMS *int64 `json:"run_duration_ms,omitempty"` +} + +// WorkflowRunEnvironment represents different runner environments available for a workflow run. +type WorkflowRunEnvironment struct { + Ubuntu *WorkflowRunBill `json:"UBUNTU,omitempty"` + MacOS *WorkflowRunBill `json:"MACOS,omitempty"` + Windows *WorkflowRunBill `json:"WINDOWS,omitempty"` +} + +// WorkflowRunBill specifies billable time for a specific environment in a workflow run. +type WorkflowRunBill struct { + TotalMS *int64 `json:"total_ms,omitempty"` + Jobs *int `json:"jobs,omitempty"` + JobRuns []*WorkflowRunJobRun `json:"job_runs,omitempty"` +} + +// WorkflowRunJobRun represents a usage of individual jobs of a specific workflow run. +type WorkflowRunJobRun struct { + JobID *int `json:"job_id,omitempty"` + DurationMS *int64 `json:"duration_ms,omitempty"` +} + +// WorkflowRunAttemptOptions specifies optional parameters to GetWorkflowRunAttempt. +type WorkflowRunAttemptOptions struct { + ExcludePullRequests *bool `url:"exclude_pull_requests,omitempty"` +} + +func (s *ActionsService) listWorkflowRuns(ctx context.Context, endpoint string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u, err := addOptions(endpoint, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runs := new(WorkflowRuns) + resp, err := s.client.Do(ctx, req, &runs) + if err != nil { + return nil, resp, err + } + + return runs, resp, nil +} + +// ListWorkflowRunsByID lists all workflow runs by workflow ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#list-workflow-runs +func (s *ActionsService) ListWorkflowRunsByID(ctx context.Context, owner, repo string, workflowID int64, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows/%v/runs", owner, repo, workflowID) + return s.listWorkflowRuns(ctx, u, opts) +} + +// ListWorkflowRunsByFileName lists all workflow runs by workflow file name. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#list-workflow-runs +func (s *ActionsService) ListWorkflowRunsByFileName(ctx context.Context, owner, repo, workflowFileName string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows/%v/runs", owner, repo, workflowFileName) + return s.listWorkflowRuns(ctx, u, opts) +} + +// ListRepositoryWorkflowRuns lists all workflow runs for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#list-workflow-runs-for-a-repository +func (s *ActionsService) ListRepositoryWorkflowRuns(ctx context.Context, owner, repo string, opts *ListWorkflowRunsOptions) (*WorkflowRuns, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/runs", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runs := new(WorkflowRuns) + resp, err := s.client.Do(ctx, req, &runs) + if err != nil { + return nil, resp, err + } + + return runs, resp, nil +} + +// GetWorkflowRunByID gets a specific workflow run by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#get-a-workflow-run +func (s *ActionsService) GetWorkflowRunByID(ctx context.Context, owner, repo string, runID int64) (*WorkflowRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v", owner, repo, runID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + run := new(WorkflowRun) + resp, err := s.client.Do(ctx, req, run) + if err != nil { + return nil, resp, err + } + + return run, resp, nil +} + +// GetWorkflowRunAttempt gets a specific workflow run attempt. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#get-a-workflow-run-attempt +func (s *ActionsService) GetWorkflowRunAttempt(ctx context.Context, owner, repo string, runID int64, attemptNumber int, opts *WorkflowRunAttemptOptions) (*WorkflowRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/attempts/%v", owner, repo, runID, attemptNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + run := new(WorkflowRun) + resp, err := s.client.Do(ctx, req, run) + if err != nil { + return nil, resp, err + } + + return run, resp, nil +} + +// RerunWorkflowByID re-runs a workflow by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#re-run-a-workflow +func (s *ActionsService) RerunWorkflowByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/rerun", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RerunFailedJobsByID re-runs all of the failed jobs and their dependent jobs in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#re-run-failed-jobs-from-a-workflow-run +func (s *ActionsService) RerunFailedJobsByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/rerun-failed-jobs", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RerunJobByID re-runs a job and its dependent jobs in a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#re-run-a-job-from-a-workflow-run +func (s *ActionsService) RerunJobByID(ctx context.Context, owner, repo string, jobID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/jobs/%v/rerun", owner, repo, jobID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CancelWorkflowRunByID cancels a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#cancel-a-workflow-run +func (s *ActionsService) CancelWorkflowRunByID(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/cancel", owner, repo, runID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetWorkflowRunLogs gets a redirect URL to download a plain text file of logs for a workflow run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#download-workflow-run-logs +func (s *ActionsService) GetWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64, followRedirects bool) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, followRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} + +// DeleteWorkflowRun deletes a workflow run by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#delete-a-workflow-run +func (s *ActionsService) DeleteWorkflowRun(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v", owner, repo, runID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteWorkflowRunLogs deletes all logs for a workflow run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#delete-workflow-run-logs +func (s *ActionsService) DeleteWorkflowRunLogs(ctx context.Context, owner, repo string, runID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/logs", owner, repo, runID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetWorkflowRunUsageByID gets a specific workflow usage run by run ID in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflow-runs#get-workflow-run-usage +func (s *ActionsService) GetWorkflowRunUsageByID(ctx context.Context, owner, repo string, runID int64) (*WorkflowRunUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/runs/%v/timing", owner, repo, runID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + workflowRunUsage := new(WorkflowRunUsage) + resp, err := s.client.Do(ctx, req, workflowRunUsage) + if err != nil { + return nil, resp, err + } + + return workflowRunUsage, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/actions_workflows.go b/vendor/github.com/google/go-github/v45/github/actions_workflows.go new file mode 100644 index 0000000000..9973a5d3f3 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/actions_workflows.go @@ -0,0 +1,218 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Workflow represents a repository action workflow. +type Workflow struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + State *string `json:"state,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + BadgeURL *string `json:"badge_url,omitempty"` +} + +// Workflows represents a slice of repository action workflows. +type Workflows struct { + TotalCount *int `json:"total_count,omitempty"` + Workflows []*Workflow `json:"workflows,omitempty"` +} + +// WorkflowUsage represents a usage of a specific workflow. +type WorkflowUsage struct { + Billable *WorkflowEnvironment `json:"billable,omitempty"` +} + +// WorkflowEnvironment represents different runner environments available for a workflow. +type WorkflowEnvironment struct { + Ubuntu *WorkflowBill `json:"UBUNTU,omitempty"` + MacOS *WorkflowBill `json:"MACOS,omitempty"` + Windows *WorkflowBill `json:"WINDOWS,omitempty"` +} + +// WorkflowBill specifies billable time for a specific environment in a workflow. +type WorkflowBill struct { + TotalMS *int64 `json:"total_ms,omitempty"` +} + +// CreateWorkflowDispatchEventRequest represents a request to create a workflow dispatch event. +type CreateWorkflowDispatchEventRequest struct { + // Ref represents the reference of the workflow run. + // The reference can be a branch or a tag. + // Ref is required when creating a workflow dispatch event. + Ref string `json:"ref"` + // Inputs represents input keys and values configured in the workflow file. + // The maximum number of properties is 10. + // Default: Any default properties configured in the workflow file will be used when `inputs` are omitted. + Inputs map[string]interface{} `json:"inputs,omitempty"` +} + +// ListWorkflows lists all workflows in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#list-repository-workflows +func (s *ActionsService) ListWorkflows(ctx context.Context, owner, repo string, opts *ListOptions) (*Workflows, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/actions/workflows", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + workflows := new(Workflows) + resp, err := s.client.Do(ctx, req, &workflows) + if err != nil { + return nil, resp, err + } + + return workflows, resp, nil +} + +// GetWorkflowByID gets a specific workflow by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#get-a-workflow +func (s *ActionsService) GetWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Workflow, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowID) + + return s.getWorkflow(ctx, u) +} + +// GetWorkflowByFileName gets a specific workflow by file name. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#get-a-workflow +func (s *ActionsService) GetWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Workflow, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowFileName) + + return s.getWorkflow(ctx, u) +} + +func (s *ActionsService) getWorkflow(ctx context.Context, url string) (*Workflow, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + workflow := new(Workflow) + resp, err := s.client.Do(ctx, req, workflow) + if err != nil { + return nil, resp, err + } + + return workflow, resp, nil +} + +// GetWorkflowUsageByID gets a specific workflow usage by ID in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#get-workflow-usage +func (s *ActionsService) GetWorkflowUsageByID(ctx context.Context, owner, repo string, workflowID int64) (*WorkflowUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/timing", owner, repo, workflowID) + + return s.getWorkflowUsage(ctx, u) +} + +// GetWorkflowUsageByFileName gets a specific workflow usage by file name in the unit of billable milliseconds. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#get-workflow-usage +func (s *ActionsService) GetWorkflowUsageByFileName(ctx context.Context, owner, repo, workflowFileName string) (*WorkflowUsage, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/timing", owner, repo, workflowFileName) + + return s.getWorkflowUsage(ctx, u) +} + +func (s *ActionsService) getWorkflowUsage(ctx context.Context, url string) (*WorkflowUsage, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + workflowUsage := new(WorkflowUsage) + resp, err := s.client.Do(ctx, req, workflowUsage) + if err != nil { + return nil, resp, err + } + + return workflowUsage, resp, nil +} + +// CreateWorkflowDispatchEventByID manually triggers a GitHub Actions workflow run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#create-a-workflow-dispatch-event +func (s *ActionsService) CreateWorkflowDispatchEventByID(ctx context.Context, owner, repo string, workflowID int64, event CreateWorkflowDispatchEventRequest) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/dispatches", owner, repo, workflowID) + + return s.createWorkflowDispatchEvent(ctx, u, &event) +} + +// CreateWorkflowDispatchEventByFileName manually triggers a GitHub Actions workflow run. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#create-a-workflow-dispatch-event +func (s *ActionsService) CreateWorkflowDispatchEventByFileName(ctx context.Context, owner, repo, workflowFileName string, event CreateWorkflowDispatchEventRequest) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/dispatches", owner, repo, workflowFileName) + + return s.createWorkflowDispatchEvent(ctx, u, &event) +} + +func (s *ActionsService) createWorkflowDispatchEvent(ctx context.Context, url string, event *CreateWorkflowDispatchEventRequest) (*Response, error) { + req, err := s.client.NewRequest("POST", url, event) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// EnableWorkflowByID enables a workflow and sets the state of the workflow to "active". +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#enable-a-workflow +func (s *ActionsService) EnableWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/enable", owner, repo, workflowID) + return s.doNewPutRequest(ctx, u) +} + +// EnableWorkflowByFileName enables a workflow and sets the state of the workflow to "active". +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#enable-a-workflow +func (s *ActionsService) EnableWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/enable", owner, repo, workflowFileName) + return s.doNewPutRequest(ctx, u) +} + +// DisableWorkflowByID disables a workflow and sets the state of the workflow to "disabled_manually". +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#disable-a-workflow +func (s *ActionsService) DisableWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/disable", owner, repo, workflowID) + return s.doNewPutRequest(ctx, u) +} + +// DisableWorkflowByFileName disables a workflow and sets the state of the workflow to "disabled_manually". +// +// GitHub API docs: https://docs.github.com/en/rest/actions/workflows#disable-a-workflow +func (s *ActionsService) DisableWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v/disable", owner, repo, workflowFileName) + return s.doNewPutRequest(ctx, u) +} + +func (s *ActionsService) doNewPutRequest(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/activity.go b/vendor/github.com/google/go-github/v45/github/activity.go new file mode 100644 index 0000000000..f99ecfcdff --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/activity.go @@ -0,0 +1,72 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// ActivityService handles communication with the activity related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/ +type ActivityService service + +// FeedLink represents a link to a related resource. +type FeedLink struct { + HRef *string `json:"href,omitempty"` + Type *string `json:"type,omitempty"` +} + +// Feeds represents timeline resources in Atom format. +type Feeds struct { + TimelineURL *string `json:"timeline_url,omitempty"` + UserURL *string `json:"user_url,omitempty"` + CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"` + CurrentUserURL *string `json:"current_user_url,omitempty"` + CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"` + CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"` + CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"` + Links *FeedLinks `json:"_links,omitempty"` +} + +// FeedLinks represents the links in a Feed. +type FeedLinks struct { + Timeline *FeedLink `json:"timeline,omitempty"` + User *FeedLink `json:"user,omitempty"` + CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"` + CurrentUser *FeedLink `json:"current_user,omitempty"` + CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"` + CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"` + CurrentUserOrganizations []*FeedLink `json:"current_user_organizations,omitempty"` +} + +// ListFeeds lists all the feeds available to the authenticated user. +// +// GitHub provides several timeline resources in Atom format: +// Timeline: The GitHub global public timeline +// User: The public timeline for any user, using URI template +// Current user public: The public timeline for the authenticated user +// Current user: The private timeline for the authenticated user +// Current user actor: The private timeline for activity created by the +// authenticated user +// Current user organizations: The private timeline for the organizations +// the authenticated user is a member of. +// +// Note: Private feeds are only returned when authenticating via Basic Auth +// since current feed URIs use the older, non revocable auth tokens. +func (s *ActivityService) ListFeeds(ctx context.Context) (*Feeds, *Response, error) { + req, err := s.client.NewRequest("GET", "feeds", nil) + if err != nil { + return nil, nil, err + } + + f := &Feeds{} + resp, err := s.client.Do(ctx, req, f) + if err != nil { + return nil, resp, err + } + + return f, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/activity_events.go b/vendor/github.com/google/go-github/v45/github/activity_events.go new file mode 100644 index 0000000000..d6f0f043b0 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/activity_events.go @@ -0,0 +1,217 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListEvents drinks from the firehose of all public events across GitHub. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-public-events +func (s *ActivityService) ListEvents(ctx context.Context, opts *ListOptions) ([]*Event, *Response, error) { + u, err := addOptions("events", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-repository-events +func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListIssueEventsForRepository lists issue events for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/events#list-issue-events-for-a-repository +func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForRepoNetwork lists public events for a network of repositories. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-public-events-for-a-network-of-repositories +func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("networks/%v/%v/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsForOrganization lists public events for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-public-organization-events +func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("orgs/%v/events", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-events-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-public-events-for-a-user +func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/events/public", user) + } else { + u = fmt.Sprintf("users/%v/events", user) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListEventsReceivedByUser lists the events received by a user. If publicOnly is +// true, only public events will be returned. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-events-received-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-public-events-received-by-a-user +func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) { + var u string + if publicOnly { + u = fmt.Sprintf("users/%v/received_events/public", user) + } else { + u = fmt.Sprintf("users/%v/received_events", user) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListUserEventsForOrganization provides the user’s organization dashboard. You +// must be authenticated as the user to view this. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/events#list-organization-events-for-the-authenticated-user +func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opts *ListOptions) ([]*Event, *Response, error) { + u := fmt.Sprintf("users/%v/events/orgs/%v", user, org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*Event + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/activity_notifications.go b/vendor/github.com/google/go-github/v45/github/activity_notifications.go new file mode 100644 index 0000000000..38a3184536 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/activity_notifications.go @@ -0,0 +1,223 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// Notification identifies a GitHub notification for a user. +type Notification struct { + ID *string `json:"id,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Subject *NotificationSubject `json:"subject,omitempty"` + + // Reason identifies the event that triggered the notification. + // + // GitHub API docs: https://docs.github.com/en/rest/activity#notification-reasons + Reason *string `json:"reason,omitempty"` + + Unread *bool `json:"unread,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + LastReadAt *time.Time `json:"last_read_at,omitempty"` + URL *string `json:"url,omitempty"` +} + +// NotificationSubject identifies the subject of a notification. +type NotificationSubject struct { + Title *string `json:"title,omitempty"` + URL *string `json:"url,omitempty"` + LatestCommentURL *string `json:"latest_comment_url,omitempty"` + Type *string `json:"type,omitempty"` +} + +// NotificationListOptions specifies the optional parameters to the +// ActivityService.ListNotifications method. +type NotificationListOptions struct { + All bool `url:"all,omitempty"` + Participating bool `url:"participating,omitempty"` + Since time.Time `url:"since,omitempty"` + Before time.Time `url:"before,omitempty"` + + ListOptions +} + +// ListNotifications lists all notifications for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/notifications#list-notifications-for-the-authenticated-user +func (s *ActivityService) ListNotifications(ctx context.Context, opts *NotificationListOptions) ([]*Notification, *Response, error) { + u := "notifications" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var notifications []*Notification + resp, err := s.client.Do(ctx, req, ¬ifications) + if err != nil { + return nil, resp, err + } + + return notifications, resp, nil +} + +// ListRepositoryNotifications lists all notifications in a given repository +// for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/notifications#list-repository-notifications-for-the-authenticated-user +func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opts *NotificationListOptions) ([]*Notification, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var notifications []*Notification + resp, err := s.client.Do(ctx, req, ¬ifications) + if err != nil { + return nil, resp, err + } + + return notifications, resp, nil +} + +type markReadOptions struct { + LastReadAt time.Time `json:"last_read_at,omitempty"` +} + +// MarkNotificationsRead marks all notifications up to lastRead as read. +// +// GitHub API docs: https://docs.github.com/en/rest/activity#mark-as-read +func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead time.Time) (*Response, error) { + opts := &markReadOptions{ + LastReadAt: lastRead, + } + req, err := s.client.NewRequest("PUT", "notifications", opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// MarkRepositoryNotificationsRead marks all notifications up to lastRead in +// the specified repository as read. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/notifications#mark-repository-notifications-as-read +func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead time.Time) (*Response, error) { + opts := &markReadOptions{ + LastReadAt: lastRead, + } + u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetThread gets the specified notification thread. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/notifications#get-a-thread +func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + notification := new(Notification) + resp, err := s.client.Do(ctx, req, notification) + if err != nil { + return nil, resp, err + } + + return notification, resp, nil +} + +// MarkThreadRead marks the specified thread as read. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/notifications#mark-a-thread-as-read +func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("notifications/threads/%v", id) + + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetThreadSubscription checks to see if the authenticated user is subscribed +// to a thread. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/notifications#get-a-thread-subscription-for-the-authenticated-user +func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// SetThreadSubscription sets the subscription for the specified thread for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/notifications#set-a-thread-subscription +func (s *ActivityService) SetThreadSubscription(ctx context.Context, id string, subscription *Subscription) (*Subscription, *Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + + req, err := s.client.NewRequest("PUT", u, subscription) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// DeleteThreadSubscription deletes the subscription for the specified thread +// for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/notifications#delete-a-thread-subscription +func (s *ActivityService) DeleteThreadSubscription(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("notifications/threads/%v/subscription", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/activity_star.go b/vendor/github.com/google/go-github/v45/github/activity_star.go new file mode 100644 index 0000000000..65a316f532 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/activity_star.go @@ -0,0 +1,141 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// StarredRepository is returned by ListStarred. +type StarredRepository struct { + StarredAt *Timestamp `json:"starred_at,omitempty"` + Repository *Repository `json:"repo,omitempty"` +} + +// Stargazer represents a user that has starred a repository. +type Stargazer struct { + StarredAt *Timestamp `json:"starred_at,omitempty"` + User *User `json:"user,omitempty"` +} + +// ListStargazers lists people who have starred the specified repo. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/starring#list-stargazers +func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Stargazer, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeStarringPreview) + + var stargazers []*Stargazer + resp, err := s.client.Do(ctx, req, &stargazers) + if err != nil { + return nil, resp, err + } + + return stargazers, resp, nil +} + +// ActivityListStarredOptions specifies the optional parameters to the +// ActivityService.ListStarred method. +type ActivityListStarredOptions struct { + // How to sort the repository list. Possible values are: created, updated, + // pushed, full_name. Default is "full_name". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Possible values are: asc, desc. + // Default is "asc" when sort is "full_name", otherwise default is "desc". + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListStarred lists all the repos starred by a user. Passing the empty string +// will list the starred repositories for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/starring#list-repositories-starred-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/activity/starring#list-repositories-starred-by-a-user +func (s *ActivityService) ListStarred(ctx context.Context, user string, opts *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/starred", user) + } else { + u = "user/starred" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when APIs fully launch + acceptHeaders := []string{mediaTypeStarringPreview, mediaTypeTopicsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var repos []*StarredRepository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// IsStarred checks if a repository is starred by authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/starring#check-if-a-repository-is-starred-by-the-authenticated-user +func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bool, *Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + starred, err := parseBoolResponse(err) + return starred, resp, err +} + +// Star a repository as the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/starring#star-a-repository-for-the-authenticated-user +func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unstar a repository as the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/starring#unstar-a-repository-for-the-authenticated-user +func (s *ActivityService) Unstar(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("user/starred/%v/%v", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/activity_watching.go b/vendor/github.com/google/go-github/v45/github/activity_watching.go new file mode 100644 index 0000000000..2d6fafcc79 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/activity_watching.go @@ -0,0 +1,147 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Subscription identifies a repository or thread subscription. +type Subscription struct { + Subscribed *bool `json:"subscribed,omitempty"` + Ignored *bool `json:"ignored,omitempty"` + Reason *string `json:"reason,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + + // only populated for repository subscriptions + RepositoryURL *string `json:"repository_url,omitempty"` + + // only populated for thread subscriptions + ThreadURL *string `json:"thread_url,omitempty"` +} + +// ListWatchers lists watchers of a particular repo. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/watching#list-watchers +func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var watchers []*User + resp, err := s.client.Do(ctx, req, &watchers) + if err != nil { + return nil, resp, err + } + + return watchers, resp, nil +} + +// ListWatched lists the repositories the specified user is watching. Passing +// the empty string will fetch watched repos for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/watching#list-repositories-watched-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/activity/watching#list-repositories-watched-by-a-user +func (s *ActivityService) ListWatched(ctx context.Context, user string, opts *ListOptions) ([]*Repository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/subscriptions", user) + } else { + u = "user/subscriptions" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var watched []*Repository + resp, err := s.client.Do(ctx, req, &watched) + if err != nil { + return nil, resp, err + } + + return watched, resp, nil +} + +// GetRepositorySubscription returns the subscription for the specified +// repository for the authenticated user. If the authenticated user is not +// watching the repository, a nil Subscription is returned. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/watching#get-a-repository-subscription +func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + // if it's just a 404, don't return that as an error + _, err = parseBoolResponse(err) + return nil, resp, err + } + + return sub, resp, nil +} + +// SetRepositorySubscription sets the subscription for the specified repository +// for the authenticated user. +// +// To watch a repository, set subscription.Subscribed to true. +// To ignore notifications made within a repository, set subscription.Ignored to true. +// To stop watching a repository, use DeleteRepositorySubscription. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/watching#set-a-repository-subscription +func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + + req, err := s.client.NewRequest("PUT", u, subscription) + if err != nil { + return nil, nil, err + } + + sub := new(Subscription) + resp, err := s.client.Do(ctx, req, sub) + if err != nil { + return nil, resp, err + } + + return sub, resp, nil +} + +// DeleteRepositorySubscription deletes the subscription for the specified +// repository for the authenticated user. +// +// This is used to stop watching a repository. To control whether or not to +// receive notifications from a repository, use SetRepositorySubscription. +// +// GitHub API docs: https://docs.github.com/en/rest/activity/watching#delete-a-repository-subscription +func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/admin.go b/vendor/github.com/google/go-github/v45/github/admin.go new file mode 100644 index 0000000000..1b28ef64c7 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/admin.go @@ -0,0 +1,119 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AdminService handles communication with the admin related methods of the +// GitHub API. These API routes are normally only accessible for GitHub +// Enterprise installations. +// +// GitHub API docs: https://docs.github.com/en/rest/enterprise-admin +type AdminService service + +// TeamLDAPMapping represents the mapping between a GitHub team and an LDAP group. +type TeamLDAPMapping struct { + ID *int64 `json:"id,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Slug *string `json:"slug,omitempty"` + Description *string `json:"description,omitempty"` + Privacy *string `json:"privacy,omitempty"` + Permission *string `json:"permission,omitempty"` + + MembersURL *string `json:"members_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` +} + +func (m TeamLDAPMapping) String() string { + return Stringify(m) +} + +// UserLDAPMapping represents the mapping between a GitHub user and an LDAP user. +type UserLDAPMapping struct { + ID *int64 `json:"id,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` + Login *string `json:"login,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` +} + +func (m UserLDAPMapping) String() string { + return Stringify(m) +} + +// Enterprise represents the GitHub enterprise profile. +type Enterprise struct { + ID *int `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + Name *string `json:"name,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + Description *string `json:"description,omitempty"` + WebsiteURL *string `json:"website_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (m Enterprise) String() string { + return Stringify(m) +} + +// UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user. +// +// GitHub API docs: https://docs.github.com/en/enterprise-server/rest/enterprise-admin/ldap#update-ldap-mapping-for-a-user +func (s *AdminService) UpdateUserLDAPMapping(ctx context.Context, user string, mapping *UserLDAPMapping) (*UserLDAPMapping, *Response, error) { + u := fmt.Sprintf("admin/ldap/users/%v/mapping", user) + req, err := s.client.NewRequest("PATCH", u, mapping) + if err != nil { + return nil, nil, err + } + + m := new(UserLDAPMapping) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// UpdateTeamLDAPMapping updates the mapping between a GitHub team and an LDAP group. +// +// GitHub API docs: https://docs.github.com/en/rest/enterprise/ldap/#update-ldap-mapping-for-a-team +func (s *AdminService) UpdateTeamLDAPMapping(ctx context.Context, team int64, mapping *TeamLDAPMapping) (*TeamLDAPMapping, *Response, error) { + u := fmt.Sprintf("admin/ldap/teams/%v/mapping", team) + req, err := s.client.NewRequest("PATCH", u, mapping) + if err != nil { + return nil, nil, err + } + + m := new(TeamLDAPMapping) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/admin_orgs.go b/vendor/github.com/google/go-github/v45/github/admin_orgs.go new file mode 100644 index 0000000000..448e51f631 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/admin_orgs.go @@ -0,0 +1,89 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// createOrgRequest is a subset of Organization and is used internally +// by CreateOrg to pass only the known fields for the endpoint. +type createOrgRequest struct { + Login *string `json:"login,omitempty"` + Admin *string `json:"admin,omitempty"` +} + +// CreateOrg creates a new organization in GitHub Enterprise. +// +// Note that only a subset of the org fields are used and org must +// not be nil. +// +// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/orgs/#create-an-organization +func (s *AdminService) CreateOrg(ctx context.Context, org *Organization, admin string) (*Organization, *Response, error) { + u := "admin/organizations" + + orgReq := &createOrgRequest{ + Login: org.Login, + Admin: &admin, + } + + req, err := s.client.NewRequest("POST", u, orgReq) + if err != nil { + return nil, nil, err + } + + o := new(Organization) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} + +// renameOrgRequest is a subset of Organization and is used internally +// by RenameOrg and RenameOrgByName to pass only the known fields for the endpoint. +type renameOrgRequest struct { + Login *string `json:"login,omitempty"` +} + +// RenameOrgResponse is the response given when renaming an Organization. +type RenameOrgResponse struct { + Message *string `json:"message,omitempty"` + URL *string `json:"url,omitempty"` +} + +// RenameOrg renames an organization in GitHub Enterprise. +// +// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/orgs/#rename-an-organization +func (s *AdminService) RenameOrg(ctx context.Context, org *Organization, newName string) (*RenameOrgResponse, *Response, error) { + return s.RenameOrgByName(ctx, *org.Login, newName) +} + +// RenameOrgByName renames an organization in GitHub Enterprise using its current name. +// +// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/orgs/#rename-an-organization +func (s *AdminService) RenameOrgByName(ctx context.Context, org, newName string) (*RenameOrgResponse, *Response, error) { + u := fmt.Sprintf("admin/organizations/%v", org) + + orgReq := &renameOrgRequest{ + Login: &newName, + } + + req, err := s.client.NewRequest("PATCH", u, orgReq) + if err != nil { + return nil, nil, err + } + + o := new(RenameOrgResponse) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/admin_stats.go b/vendor/github.com/google/go-github/v45/github/admin_stats.go new file mode 100644 index 0000000000..ef294f4479 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/admin_stats.go @@ -0,0 +1,171 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AdminStats represents a variety of stats of a GitHub Enterprise +// installation. +type AdminStats struct { + Issues *IssueStats `json:"issues,omitempty"` + Hooks *HookStats `json:"hooks,omitempty"` + Milestones *MilestoneStats `json:"milestones,omitempty"` + Orgs *OrgStats `json:"orgs,omitempty"` + Comments *CommentStats `json:"comments,omitempty"` + Pages *PageStats `json:"pages,omitempty"` + Users *UserStats `json:"users,omitempty"` + Gists *GistStats `json:"gists,omitempty"` + Pulls *PullStats `json:"pulls,omitempty"` + Repos *RepoStats `json:"repos,omitempty"` +} + +func (s AdminStats) String() string { + return Stringify(s) +} + +// IssueStats represents the number of total, open and closed issues. +type IssueStats struct { + TotalIssues *int `json:"total_issues,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` + ClosedIssues *int `json:"closed_issues,omitempty"` +} + +func (s IssueStats) String() string { + return Stringify(s) +} + +// HookStats represents the number of total, active and inactive hooks. +type HookStats struct { + TotalHooks *int `json:"total_hooks,omitempty"` + ActiveHooks *int `json:"active_hooks,omitempty"` + InactiveHooks *int `json:"inactive_hooks,omitempty"` +} + +func (s HookStats) String() string { + return Stringify(s) +} + +// MilestoneStats represents the number of total, open and close milestones. +type MilestoneStats struct { + TotalMilestones *int `json:"total_milestones,omitempty"` + OpenMilestones *int `json:"open_milestones,omitempty"` + ClosedMilestones *int `json:"closed_milestones,omitempty"` +} + +func (s MilestoneStats) String() string { + return Stringify(s) +} + +// OrgStats represents the number of total, disabled organizations and the team +// and team member count. +type OrgStats struct { + TotalOrgs *int `json:"total_orgs,omitempty"` + DisabledOrgs *int `json:"disabled_orgs,omitempty"` + TotalTeams *int `json:"total_teams,omitempty"` + TotalTeamMembers *int `json:"total_team_members,omitempty"` +} + +func (s OrgStats) String() string { + return Stringify(s) +} + +// CommentStats represents the number of total comments on commits, gists, issues +// and pull requests. +type CommentStats struct { + TotalCommitComments *int `json:"total_commit_comments,omitempty"` + TotalGistComments *int `json:"total_gist_comments,omitempty"` + TotalIssueComments *int `json:"total_issue_comments,omitempty"` + TotalPullRequestComments *int `json:"total_pull_request_comments,omitempty"` +} + +func (s CommentStats) String() string { + return Stringify(s) +} + +// PageStats represents the total number of github pages. +type PageStats struct { + TotalPages *int `json:"total_pages,omitempty"` +} + +func (s PageStats) String() string { + return Stringify(s) +} + +// UserStats represents the number of total, admin and suspended users. +type UserStats struct { + TotalUsers *int `json:"total_users,omitempty"` + AdminUsers *int `json:"admin_users,omitempty"` + SuspendedUsers *int `json:"suspended_users,omitempty"` +} + +func (s UserStats) String() string { + return Stringify(s) +} + +// GistStats represents the number of total, private and public gists. +type GistStats struct { + TotalGists *int `json:"total_gists,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` +} + +func (s GistStats) String() string { + return Stringify(s) +} + +// PullStats represents the number of total, merged, mergable and unmergeable +// pull-requests. +type PullStats struct { + TotalPulls *int `json:"total_pulls,omitempty"` + MergedPulls *int `json:"merged_pulls,omitempty"` + MergablePulls *int `json:"mergeable_pulls,omitempty"` + UnmergablePulls *int `json:"unmergeable_pulls,omitempty"` +} + +func (s PullStats) String() string { + return Stringify(s) +} + +// RepoStats represents the number of total, root, fork, organization repositories +// together with the total number of pushes and wikis. +type RepoStats struct { + TotalRepos *int `json:"total_repos,omitempty"` + RootRepos *int `json:"root_repos,omitempty"` + ForkRepos *int `json:"fork_repos,omitempty"` + OrgRepos *int `json:"org_repos,omitempty"` + TotalPushes *int `json:"total_pushes,omitempty"` + TotalWikis *int `json:"total_wikis,omitempty"` +} + +func (s RepoStats) String() string { + return Stringify(s) +} + +// GetAdminStats returns a variety of metrics about a GitHub Enterprise +// installation. +// +// Please note that this is only available to site administrators, +// otherwise it will error with a 404 not found (instead of 401 or 403). +// +// GitHub API docs: https://docs.github.com/en/rest/enterprise-admin/admin_stats/ +func (s *AdminService) GetAdminStats(ctx context.Context) (*AdminStats, *Response, error) { + u := fmt.Sprintf("enterprise/stats/all") + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + m := new(AdminStats) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/admin_users.go b/vendor/github.com/google/go-github/v45/github/admin_users.go new file mode 100644 index 0000000000..d756a77e20 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/admin_users.go @@ -0,0 +1,133 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// createUserRequest is a subset of User and is used internally +// by CreateUser to pass only the known fields for the endpoint. +type createUserRequest struct { + Login *string `json:"login,omitempty"` + Email *string `json:"email,omitempty"` +} + +// CreateUser creates a new user in GitHub Enterprise. +// +// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-a-new-user +func (s *AdminService) CreateUser(ctx context.Context, login, email string) (*User, *Response, error) { + u := "admin/users" + + userReq := &createUserRequest{ + Login: &login, + Email: &email, + } + + req, err := s.client.NewRequest("POST", u, userReq) + if err != nil { + return nil, nil, err + } + + var user User + resp, err := s.client.Do(ctx, req, &user) + if err != nil { + return nil, resp, err + } + + return &user, resp, nil +} + +// DeleteUser deletes a user in GitHub Enterprise. +// +// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-a-user +func (s *AdminService) DeleteUser(ctx context.Context, username string) (*Response, error) { + u := "admin/users/" + username + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// ImpersonateUserOptions represents the scoping for the OAuth token. +type ImpersonateUserOptions struct { + Scopes []string `json:"scopes,omitempty"` +} + +// OAuthAPP represents the GitHub Site Administrator OAuth app. +type OAuthAPP struct { + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + ClientID *string `json:"client_id,omitempty"` +} + +func (s OAuthAPP) String() string { + return Stringify(s) +} + +// UserAuthorization represents the impersonation response. +type UserAuthorization struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Scopes []string `json:"scopes,omitempty"` + Token *string `json:"token,omitempty"` + TokenLastEight *string `json:"token_last_eight,omitempty"` + HashedToken *string `json:"hashed_token,omitempty"` + App *OAuthAPP `json:"app,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +// CreateUserImpersonation creates an impersonation OAuth token. +// +// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-an-impersonation-oauth-token +func (s *AdminService) CreateUserImpersonation(ctx context.Context, username string, opts *ImpersonateUserOptions) (*UserAuthorization, *Response, error) { + u := fmt.Sprintf("admin/users/%s/authorizations", username) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + a := new(UserAuthorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// DeleteUserImpersonation deletes an impersonation OAuth token. +// +// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-an-impersonation-oauth-token +func (s *AdminService) DeleteUserImpersonation(ctx context.Context, username string) (*Response, error) { + u := fmt.Sprintf("admin/users/%s/authorizations", username) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/apps.go b/vendor/github.com/google/go-github/v45/github/apps.go new file mode 100644 index 0000000000..dff9b210f2 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/apps.go @@ -0,0 +1,356 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// AppsService provides access to the installation related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/ +type AppsService service + +// App represents a GitHub App. +type App struct { + ID *int64 `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + ExternalURL *string `json:"external_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + Events []string `json:"events,omitempty"` +} + +// InstallationToken represents an installation token. +type InstallationToken struct { + Token *string `json:"token,omitempty"` + ExpiresAt *time.Time `json:"expires_at,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +// InstallationTokenOptions allow restricting a token's access to specific repositories. +type InstallationTokenOptions struct { + // The IDs of the repositories that the installation token can access. + // Providing repository IDs restricts the access of an installation token to specific repositories. + RepositoryIDs []int64 `json:"repository_ids,omitempty"` + + // The names of the repositories that the installation token can access. + // Providing repository names restricts the access of an installation token to specific repositories. + Repositories []string `json:"repositories,omitempty"` + + // The permissions granted to the access token. + // The permissions object includes the permission names and their access type. + Permissions *InstallationPermissions `json:"permissions,omitempty"` +} + +// InstallationPermissions lists the repository and organization permissions for an installation. +// +// Permission names taken from: +// https://docs.github.com/en/enterprise-server@3.0/rest/apps#create-an-installation-access-token-for-an-app +// https://docs.github.com/en/rest/apps#create-an-installation-access-token-for-an-app +type InstallationPermissions struct { + Actions *string `json:"actions,omitempty"` + Administration *string `json:"administration,omitempty"` + Blocking *string `json:"blocking,omitempty"` + Checks *string `json:"checks,omitempty"` + Contents *string `json:"contents,omitempty"` + ContentReferences *string `json:"content_references,omitempty"` + Deployments *string `json:"deployments,omitempty"` + Emails *string `json:"emails,omitempty"` + Environments *string `json:"environments,omitempty"` + Followers *string `json:"followers,omitempty"` + Issues *string `json:"issues,omitempty"` + Metadata *string `json:"metadata,omitempty"` + Members *string `json:"members,omitempty"` + OrganizationAdministration *string `json:"organization_administration,omitempty"` + OrganizationHooks *string `json:"organization_hooks,omitempty"` + OrganizationPlan *string `json:"organization_plan,omitempty"` + OrganizationPreReceiveHooks *string `json:"organization_pre_receive_hooks,omitempty"` + OrganizationProjects *string `json:"organization_projects,omitempty"` + OrganizationSecrets *string `json:"organization_secrets,omitempty"` + OrganizationSelfHostedRunners *string `json:"organization_self_hosted_runners,omitempty"` + OrganizationUserBlocking *string `json:"organization_user_blocking,omitempty"` + Packages *string `json:"packages,omitempty"` + Pages *string `json:"pages,omitempty"` + PullRequests *string `json:"pull_requests,omitempty"` + RepositoryHooks *string `json:"repository_hooks,omitempty"` + RepositoryProjects *string `json:"repository_projects,omitempty"` + RepositoryPreReceiveHooks *string `json:"repository_pre_receive_hooks,omitempty"` + Secrets *string `json:"secrets,omitempty"` + SecretScanningAlerts *string `json:"secret_scanning_alerts,omitempty"` + SecurityEvents *string `json:"security_events,omitempty"` + SingleFile *string `json:"single_file,omitempty"` + Statuses *string `json:"statuses,omitempty"` + TeamDiscussions *string `json:"team_discussions,omitempty"` + VulnerabilityAlerts *string `json:"vulnerability_alerts,omitempty"` + Workflows *string `json:"workflows,omitempty"` +} + +// Installation represents a GitHub Apps installation. +type Installation struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AppID *int64 `json:"app_id,omitempty"` + AppSlug *string `json:"app_slug,omitempty"` + TargetID *int64 `json:"target_id,omitempty"` + Account *User `json:"account,omitempty"` + AccessTokensURL *string `json:"access_tokens_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + TargetType *string `json:"target_type,omitempty"` + SingleFileName *string `json:"single_file_name,omitempty"` + RepositorySelection *string `json:"repository_selection,omitempty"` + Events []string `json:"events,omitempty"` + SingleFilePaths []string `json:"single_file_paths,omitempty"` + Permissions *InstallationPermissions `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + HasMultipleSingleFiles *bool `json:"has_multiple_single_files,omitempty"` + SuspendedBy *User `json:"suspended_by,omitempty"` + SuspendedAt *Timestamp `json:"suspended_at,omitempty"` +} + +// Attachment represents a GitHub Apps attachment. +type Attachment struct { + ID *int64 `json:"id,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` +} + +// ContentReference represents a reference to a URL in an issue or pull request. +type ContentReference struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Reference *string `json:"reference,omitempty"` +} + +func (i Installation) String() string { + return Stringify(i) +} + +// Get a single GitHub App. Passing the empty string will get +// the authenticated GitHub App. +// +// Note: appSlug is just the URL-friendly name of your GitHub App. +// You can find this on the settings page for your GitHub App +// (e.g., https://github.com/settings/apps/:app_slug). +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#get-the-authenticated-app +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#get-an-app +func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) { + var u string + if appSlug != "" { + u = fmt.Sprintf("apps/%v", appSlug) + } else { + u = "app" + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + app := new(App) + resp, err := s.client.Do(ctx, req, app) + if err != nil { + return nil, resp, err + } + + return app, resp, nil +} + +// ListInstallations lists the installations that the current GitHub App has. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#list-installations-for-the-authenticated-app +func (s *AppsService) ListInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) { + u, err := addOptions("app/installations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var i []*Installation + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// GetInstallation returns the specified installation. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#get-an-installation-for-the-authenticated-app +func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id)) +} + +// ListUserInstallations lists installations that are accessible to the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/installations#list-app-installations-accessible-to-the-user-access-token +func (s *AppsService) ListUserInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) { + u, err := addOptions("user/installations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var i struct { + Installations []*Installation `json:"installations"` + } + resp, err := s.client.Do(ctx, req, &i) + if err != nil { + return nil, resp, err + } + + return i.Installations, resp, nil +} + +// SuspendInstallation suspends the specified installation. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#suspend-an-app-installation +func (s *AppsService) SuspendInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v/suspended", id) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UnsuspendInstallation unsuspends the specified installation. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#unsuspend-an-app-installation +func (s *AppsService) UnsuspendInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v/suspended", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteInstallation deletes the specified installation. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#delete-an-installation-for-the-authenticated-app +func (s *AppsService) DeleteInstallation(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("app/installations/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateInstallationToken creates a new installation token. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#create-an-installation-access-token-for-an-app +func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64, opts *InstallationTokenOptions) (*InstallationToken, *Response, error) { + u := fmt.Sprintf("app/installations/%v/access_tokens", id) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(InstallationToken) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// CreateAttachment creates a new attachment on user comment containing a url. +// +// TODO: Find GitHub API docs. +func (s *AppsService) CreateAttachment(ctx context.Context, contentReferenceID int64, title, body string) (*Attachment, *Response, error) { + u := fmt.Sprintf("content_references/%v/attachments", contentReferenceID) + payload := &Attachment{Title: String(title), Body: String(body)} + req, err := s.client.NewRequest("POST", u, payload) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeContentAttachmentsPreview) + + m := &Attachment{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// FindOrganizationInstallation finds the organization's installation information. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#get-an-organization-installation-for-the-authenticated-app +func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org)) +} + +// FindRepositoryInstallation finds the repository's installation information. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#get-a-repository-installation-for-the-authenticated-app +func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo)) +} + +// FindRepositoryInstallationByID finds the repository's installation information. +// +// Note: FindRepositoryInstallationByID uses the undocumented GitHub API endpoint /repositories/:id/installation. +func (s *AppsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("repositories/%d/installation", id)) +} + +// FindUserInstallation finds the user's installation information. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#get-a-user-installation-for-the-authenticated-app +func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) { + return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user)) +} + +func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + i := new(Installation) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/apps_hooks.go b/vendor/github.com/google/go-github/v45/github/apps_hooks.go new file mode 100644 index 0000000000..e3bd2afc03 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/apps_hooks.go @@ -0,0 +1,48 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" +) + +// GetHookConfig returns the webhook configuration for a GitHub App. +// The underlying transport must be authenticated as an app. +// +// GitHub API docs: https://docs.github.com/en/rest/apps#get-a-webhook-configuration-for-an-app +func (s *AppsService) GetHookConfig(ctx context.Context) (*HookConfig, *Response, error) { + req, err := s.client.NewRequest("GET", "app/hook/config", nil) + if err != nil { + return nil, nil, err + } + + config := new(HookConfig) + resp, err := s.client.Do(ctx, req, &config) + if err != nil { + return nil, resp, err + } + + return config, resp, nil +} + +// UpdateHookConfig updates the webhook configuration for a GitHub App. +// The underlying transport must be authenticated as an app. +// +// GitHub API docs: https://docs.github.com/en/rest/apps#update-a-webhook-configuration-for-an-app +func (s *AppsService) UpdateHookConfig(ctx context.Context, config *HookConfig) (*HookConfig, *Response, error) { + req, err := s.client.NewRequest("PATCH", "app/hook/config", config) + if err != nil { + return nil, nil, err + } + + c := new(HookConfig) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/apps_hooks_deliveries.go b/vendor/github.com/google/go-github/v45/github/apps_hooks_deliveries.go new file mode 100644 index 0000000000..33102f36d2 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/apps_hooks_deliveries.go @@ -0,0 +1,72 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHookDeliveries lists deliveries of an App webhook. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/webhooks#list-deliveries-for-an-app-webhook +func (s *AppsService) ListHookDeliveries(ctx context.Context, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u, err := addOptions("app/hook/deliveries", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns the App webhook delivery with the specified ID. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/webhooks#get-a-delivery-for-an-app-webhook +func (s *AppsService) GetHookDelivery(ctx context.Context, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("app/hook/deliveries/%v", deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for an App webhook. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/webhooks#redeliver-a-delivery-for-an-app-webhook +func (s *AppsService) RedeliverHookDelivery(ctx context.Context, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("app/hook/deliveries/%v/attempts", deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/apps_installation.go b/vendor/github.com/google/go-github/v45/github/apps_installation.go new file mode 100644 index 0000000000..b619080713 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/apps_installation.go @@ -0,0 +1,128 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" +) + +// ListRepositories represents the response from the list repos endpoints. +type ListRepositories struct { + TotalCount *int `json:"total_count,omitempty"` + Repositories []*Repository `json:"repositories"` +} + +// ListRepos lists the repositories that are accessible to the authenticated installation. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/installations#list-repositories-accessible-to-the-app-installation +func (s *AppsService) ListRepos(ctx context.Context, opts *ListOptions) (*ListRepositories, *Response, error) { + u, err := addOptions("installation/repositories", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{ + mediaTypeTopicsPreview, + mediaTypeRepositoryVisibilityPreview, + mediaTypeRepositoryTemplatePreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var r *ListRepositories + + resp, err := s.client.Do(ctx, req, &r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// ListUserRepos lists repositories that are accessible +// to the authenticated user for an installation. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/installations#list-repositories-accessible-to-the-user-access-token +func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opts *ListOptions) (*ListRepositories, *Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{ + mediaTypeTopicsPreview, + mediaTypeRepositoryVisibilityPreview, + mediaTypeRepositoryTemplatePreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var r *ListRepositories + resp, err := s.client.Do(ctx, req, &r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// AddRepository adds a single repository to an installation. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/installations#add-a-repository-to-an-app-installation +func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemoveRepository removes a single repository from an installation. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/installations#remove-a-repository-from-an-app-installation +func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) { + u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RevokeInstallationToken revokes an installation token. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/installations#revoke-an-installation-access-token +func (s *AppsService) RevokeInstallationToken(ctx context.Context) (*Response, error) { + u := "installation/token" + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/apps_manifest.go b/vendor/github.com/google/go-github/v45/github/apps_manifest.go new file mode 100644 index 0000000000..fa4c85379c --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/apps_manifest.go @@ -0,0 +1,49 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AppConfig describes the configuration of a GitHub App. +type AppConfig struct { + ID *int64 `json:"id,omitempty"` + Slug *string `json:"slug,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + ExternalURL *string `json:"external_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ClientID *string `json:"client_id,omitempty"` + ClientSecret *string `json:"client_secret,omitempty"` + WebhookSecret *string `json:"webhook_secret,omitempty"` + PEM *string `json:"pem,omitempty"` +} + +// CompleteAppManifest completes the App manifest handshake flow for the given +// code. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/apps#create-a-github-app-from-a-manifest +func (s *AppsService) CompleteAppManifest(ctx context.Context, code string) (*AppConfig, *Response, error) { + u := fmt.Sprintf("app-manifests/%s/conversions", code) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + cfg := new(AppConfig) + resp, err := s.client.Do(ctx, req, cfg) + if err != nil { + return nil, resp, err + } + + return cfg, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/apps_marketplace.go b/vendor/github.com/google/go-github/v45/github/apps_marketplace.go new file mode 100644 index 0000000000..8253013684 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/apps_marketplace.go @@ -0,0 +1,180 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// MarketplaceService handles communication with the marketplace related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/apps#marketplace +type MarketplaceService struct { + client *Client + // Stubbed controls whether endpoints that return stubbed data are used + // instead of production endpoints. Stubbed data is fake data that's useful + // for testing your GitHub Apps. Stubbed data is hard-coded and will not + // change based on actual subscriptions. + // + // GitHub API docs: https://docs.github.com/en/rest/apps#testing-with-stubbed-endpoints + Stubbed bool +} + +// MarketplacePlan represents a GitHub Apps Marketplace Listing Plan. +type MarketplacePlan struct { + URL *string `json:"url,omitempty"` + AccountsURL *string `json:"accounts_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + MonthlyPriceInCents *int `json:"monthly_price_in_cents,omitempty"` + YearlyPriceInCents *int `json:"yearly_price_in_cents,omitempty"` + // The pricing model for this listing. Can be one of "flat-rate", "per-unit", or "free". + PriceModel *string `json:"price_model,omitempty"` + UnitName *string `json:"unit_name,omitempty"` + Bullets *[]string `json:"bullets,omitempty"` + // State can be one of the values "draft" or "published". + State *string `json:"state,omitempty"` + HasFreeTrial *bool `json:"has_free_trial,omitempty"` +} + +// MarketplacePurchase represents a GitHub Apps Marketplace Purchase. +type MarketplacePurchase struct { + // BillingCycle can be one of the values "yearly", "monthly" or nil. + BillingCycle *string `json:"billing_cycle,omitempty"` + NextBillingDate *Timestamp `json:"next_billing_date,omitempty"` + UnitCount *int `json:"unit_count,omitempty"` + Plan *MarketplacePlan `json:"plan,omitempty"` + OnFreeTrial *bool `json:"on_free_trial,omitempty"` + FreeTrialEndsOn *Timestamp `json:"free_trial_ends_on,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// MarketplacePendingChange represents a pending change to a GitHub Apps Marketplace Plan. +type MarketplacePendingChange struct { + EffectiveDate *Timestamp `json:"effective_date,omitempty"` + UnitCount *int `json:"unit_count,omitempty"` + ID *int64 `json:"id,omitempty"` + Plan *MarketplacePlan `json:"plan,omitempty"` +} + +// MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan. +type MarketplacePlanAccount struct { + URL *string `json:"url,omitempty"` + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` + Login *string `json:"login,omitempty"` + OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"` + MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` + MarketplacePendingChange *MarketplacePendingChange `json:"marketplace_pending_change,omitempty"` +} + +// ListPlans lists all plans for your Marketplace listing. +// +// GitHub API docs: https://docs.github.com/en/rest/apps#list-plans +func (s *MarketplaceService) ListPlans(ctx context.Context, opts *ListOptions) ([]*MarketplacePlan, *Response, error) { + uri := s.marketplaceURI("plans") + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var plans []*MarketplacePlan + resp, err := s.client.Do(ctx, req, &plans) + if err != nil { + return nil, resp, err + } + + return plans, resp, nil +} + +// ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan. +// +// GitHub API docs: https://docs.github.com/en/rest/apps#list-accounts-for-a-plan +func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opts *ListOptions) ([]*MarketplacePlanAccount, *Response, error) { + uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID)) + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var accounts []*MarketplacePlanAccount + resp, err := s.client.Do(ctx, req, &accounts) + if err != nil { + return nil, resp, err + } + + return accounts, resp, nil +} + +// GetPlanAccountForAccount get GitHub account (user or organization) associated with an account. +// +// GitHub API docs: https://docs.github.com/en/rest/apps#get-a-subscription-plan-for-an-account +func (s *MarketplaceService) GetPlanAccountForAccount(ctx context.Context, accountID int64) (*MarketplacePlanAccount, *Response, error) { + uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID)) + + req, err := s.client.NewRequest("GET", uri, nil) + if err != nil { + return nil, nil, err + } + + var account *MarketplacePlanAccount + resp, err := s.client.Do(ctx, req, &account) + if err != nil { + return nil, resp, err + } + + return account, resp, nil +} + +// ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/marketplace#list-subscriptions-for-the-authenticated-user-stubbed +// GitHub API docs: https://docs.github.com/en/rest/apps/marketplace#list-subscriptions-for-the-authenticated-user +func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opts *ListOptions) ([]*MarketplacePurchase, *Response, error) { + uri := "user/marketplace_purchases" + if s.Stubbed { + uri = "user/marketplace_purchases/stubbed" + } + + u, err := addOptions(uri, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var purchases []*MarketplacePurchase + resp, err := s.client.Do(ctx, req, &purchases) + if err != nil { + return nil, resp, err + } + return purchases, resp, nil +} + +func (s *MarketplaceService) marketplaceURI(endpoint string) string { + url := "marketplace_listing" + if s.Stubbed { + url = "marketplace_listing/stubbed" + } + return url + "/" + endpoint +} diff --git a/vendor/github.com/google/go-github/v45/github/authorizations.go b/vendor/github.com/google/go-github/v45/github/authorizations.go new file mode 100644 index 0000000000..ea0897e362 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/authorizations.go @@ -0,0 +1,281 @@ +// Copyright 2015 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Scope models a GitHub authorization scope. +// +// GitHub API docs: https://docs.github.com/en/rest/oauth/#scopes +type Scope string + +// This is the set of scopes for GitHub API V3 +const ( + ScopeNone Scope = "(no scope)" // REVISIT: is this actually returned, or just a documentation artifact? + ScopeUser Scope = "user" + ScopeUserEmail Scope = "user:email" + ScopeUserFollow Scope = "user:follow" + ScopePublicRepo Scope = "public_repo" + ScopeRepo Scope = "repo" + ScopeRepoDeployment Scope = "repo_deployment" + ScopeRepoStatus Scope = "repo:status" + ScopeDeleteRepo Scope = "delete_repo" + ScopeNotifications Scope = "notifications" + ScopeGist Scope = "gist" + ScopeReadRepoHook Scope = "read:repo_hook" + ScopeWriteRepoHook Scope = "write:repo_hook" + ScopeAdminRepoHook Scope = "admin:repo_hook" + ScopeAdminOrgHook Scope = "admin:org_hook" + ScopeReadOrg Scope = "read:org" + ScopeWriteOrg Scope = "write:org" + ScopeAdminOrg Scope = "admin:org" + ScopeReadPublicKey Scope = "read:public_key" + ScopeWritePublicKey Scope = "write:public_key" + ScopeAdminPublicKey Scope = "admin:public_key" + ScopeReadGPGKey Scope = "read:gpg_key" + ScopeWriteGPGKey Scope = "write:gpg_key" + ScopeAdminGPGKey Scope = "admin:gpg_key" + ScopeSecurityEvents Scope = "security_events" +) + +// AuthorizationsService handles communication with the authorization related +// methods of the GitHub API. +// +// This service requires HTTP Basic Authentication; it cannot be accessed using +// an OAuth token. +// +// GitHub API docs: https://docs.github.com/en/rest/oauth-authorizations +type AuthorizationsService service + +// Authorization represents an individual GitHub authorization. +type Authorization struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Scopes []Scope `json:"scopes,omitempty"` + Token *string `json:"token,omitempty"` + TokenLastEight *string `json:"token_last_eight,omitempty"` + HashedToken *string `json:"hashed_token,omitempty"` + App *AuthorizationApp `json:"app,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` + + // User is only populated by the Check and Reset methods. + User *User `json:"user,omitempty"` +} + +func (a Authorization) String() string { + return Stringify(a) +} + +// AuthorizationApp represents an individual GitHub app (in the context of authorization). +type AuthorizationApp struct { + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + ClientID *string `json:"client_id,omitempty"` +} + +func (a AuthorizationApp) String() string { + return Stringify(a) +} + +// Grant represents an OAuth application that has been granted access to an account. +type Grant struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + App *AuthorizationApp `json:"app,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Scopes []string `json:"scopes,omitempty"` +} + +func (g Grant) String() string { + return Stringify(g) +} + +// AuthorizationRequest represents a request to create an authorization. +type AuthorizationRequest struct { + Scopes []Scope `json:"scopes,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + ClientID *string `json:"client_id,omitempty"` + ClientSecret *string `json:"client_secret,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +func (a AuthorizationRequest) String() string { + return Stringify(a) +} + +// AuthorizationUpdateRequest represents a request to update an authorization. +// +// Note that for any one update, you must only provide one of the "scopes" +// fields. That is, you may provide only one of "Scopes", or "AddScopes", or +// "RemoveScopes". +// +// GitHub API docs: https://docs.github.com/en/rest/oauth-authorizations#update-an-existing-authorization +type AuthorizationUpdateRequest struct { + Scopes []string `json:"scopes,omitempty"` + AddScopes []string `json:"add_scopes,omitempty"` + RemoveScopes []string `json:"remove_scopes,omitempty"` + Note *string `json:"note,omitempty"` + NoteURL *string `json:"note_url,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` +} + +func (a AuthorizationUpdateRequest) String() string { + return Stringify(a) +} + +// Check if an OAuth token is valid for a specific app. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// The returned Authorization.User field will be populated. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/oauth-applications#check-a-token +func (s *AuthorizationsService) Check(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("POST", u, reqBody) + if err != nil { + return nil, nil, err + } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// Reset is used to reset a valid OAuth token without end user involvement. +// Applications must save the "token" property in the response, because changes +// take effect immediately. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// The returned Authorization.User field will be populated. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/oauth-applications#reset-a-token +func (s *AuthorizationsService) Reset(ctx context.Context, clientID, accessToken string) (*Authorization, *Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("PATCH", u, reqBody) + if err != nil { + return nil, nil, err + } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// Revoke an authorization for an application. +// +// Note that this operation requires the use of BasicAuth, but where the +// username is the OAuth application clientID, and the password is its +// clientSecret. Invalid tokens will return a 404 Not Found. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/oauth-applications#delete-an-app-token +func (s *AuthorizationsService) Revoke(ctx context.Context, clientID, accessToken string) (*Response, error) { + u := fmt.Sprintf("applications/%v/token", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("DELETE", u, reqBody) + if err != nil { + return nil, err + } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) + + return s.client.Do(ctx, req, nil) +} + +// DeleteGrant deletes an OAuth application grant. Deleting an application's +// grant will also delete all OAuth tokens associated with the application for +// the user. +// +// GitHub API docs: https://docs.github.com/en/rest/apps/oauth-applications#delete-an-app-authorization +func (s *AuthorizationsService) DeleteGrant(ctx context.Context, clientID, accessToken string) (*Response, error) { + u := fmt.Sprintf("applications/%v/grant", clientID) + + reqBody := &struct { + AccessToken string `json:"access_token"` + }{AccessToken: accessToken} + + req, err := s.client.NewRequest("DELETE", u, reqBody) + if err != nil { + return nil, err + } + req.Header.Set("Accept", mediaTypeOAuthAppPreview) + + return s.client.Do(ctx, req, nil) +} + +// CreateImpersonation creates an impersonation OAuth token. +// +// This requires admin permissions. With the returned Authorization.Token +// you can e.g. create or delete a user's public SSH key. NOTE: creating a +// new token automatically revokes an existing one. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-an-impersonation-oauth-token +func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, username string, authReq *AuthorizationRequest) (*Authorization, *Response, error) { + u := fmt.Sprintf("admin/users/%v/authorizations", username) + req, err := s.client.NewRequest("POST", u, authReq) + if err != nil { + return nil, nil, err + } + + a := new(Authorization) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + return a, resp, nil +} + +// DeleteImpersonation deletes an impersonation OAuth token. +// +// NOTE: there can be only one at a time. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-an-impersonation-oauth-token +func (s *AuthorizationsService) DeleteImpersonation(ctx context.Context, username string) (*Response, error) { + u := fmt.Sprintf("admin/users/%v/authorizations", username) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/billing.go b/vendor/github.com/google/go-github/v45/github/billing.go new file mode 100644 index 0000000000..d516cd0c29 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/billing.go @@ -0,0 +1,199 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// BillingService provides access to the billing related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/billing +type BillingService service + +// ActionBilling represents a GitHub Action billing. +type ActionBilling struct { + TotalMinutesUsed int `json:"total_minutes_used"` + TotalPaidMinutesUsed float64 `json:"total_paid_minutes_used"` + IncludedMinutes int `json:"included_minutes"` + MinutesUsedBreakdown MinutesUsedBreakdown `json:"minutes_used_breakdown"` +} + +type MinutesUsedBreakdown struct { + Ubuntu int `json:"UBUNTU"` + MacOS int `json:"MACOS"` + Windows int `json:"WINDOWS"` +} + +// PackageBilling represents a GitHub Package billing. +type PackageBilling struct { + TotalGigabytesBandwidthUsed int `json:"total_gigabytes_bandwidth_used"` + TotalPaidGigabytesBandwidthUsed int `json:"total_paid_gigabytes_bandwidth_used"` + IncludedGigabytesBandwidth int `json:"included_gigabytes_bandwidth"` +} + +// StorageBilling represents a GitHub Storage billing. +type StorageBilling struct { + DaysLeftInBillingCycle int `json:"days_left_in_billing_cycle"` + EstimatedPaidStorageForMonth float64 `json:"estimated_paid_storage_for_month"` + EstimatedStorageForMonth int `json:"estimated_storage_for_month"` +} + +// ActiveCommitters represents the total active committers across all repositories in an Organization. +type ActiveCommitters struct { + TotalAdvancedSecurityCommitters int `json:"total_advanced_security_committers"` + Repositories []*RepositoryActiveCommitters `json:"repositories,omitempty"` +} + +// RepositoryActiveCommitters represents active committers on each repository. +type RepositoryActiveCommitters struct { + Name *string `json:"name,omitempty"` + AdvancedSecurityCommitters *int `json:"advanced_security_committers,omitempty"` + AdvancedSecurityCommittersBreakdown []*AdvancedSecurityCommittersBreakdown `json:"advanced_security_committers_breakdown,omitempty"` +} + +// AdvancedSecurityCommittersBreakdown represents the user activity breakdown for ActiveCommitters. +type AdvancedSecurityCommittersBreakdown struct { + UserLogin *string `json:"user_login,omitempty"` + LastPushedDate *string `json:"last_pushed_date,omitempty"` +} + +// GetActionsBillingOrg returns the summary of the free and paid GitHub Actions minutes used for an Org. +// +// GitHub API docs: https://docs.github.com/en/rest/billing#get-github-actions-billing-for-an-organization +func (s *BillingService) GetActionsBillingOrg(ctx context.Context, org string) (*ActionBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/actions", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsOrgBilling := new(ActionBilling) + resp, err := s.client.Do(ctx, req, actionsOrgBilling) + if err != nil { + return nil, resp, err + } + + return actionsOrgBilling, resp, nil +} + +// GetPackagesBillingOrg returns the free and paid storage used for GitHub Packages in gigabytes for an Org. +// +// GitHub API docs: https://docs.github.com/en/rest/billing#get-github-packages-billing-for-an-organization +func (s *BillingService) GetPackagesBillingOrg(ctx context.Context, org string) (*PackageBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/packages", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + packagesOrgBilling := new(PackageBilling) + resp, err := s.client.Do(ctx, req, packagesOrgBilling) + if err != nil { + return nil, resp, err + } + + return packagesOrgBilling, resp, nil +} + +// GetStorageBillingOrg returns the estimated paid and estimated total storage used for GitHub Actions +// and GitHub Packages in gigabytes for an Org. +// +// GitHub API docs: https://docs.github.com/en/rest/billing#get-shared-storage-billing-for-an-organization +func (s *BillingService) GetStorageBillingOrg(ctx context.Context, org string) (*StorageBilling, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/shared-storage", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + storageOrgBilling := new(StorageBilling) + resp, err := s.client.Do(ctx, req, storageOrgBilling) + if err != nil { + return nil, resp, err + } + + return storageOrgBilling, resp, nil +} + +// GetAdvancedSecurityActiveCommittersOrg returns the GitHub Advanced Security active committers for an organization per repository. +// +// GitHub API docs: https://docs.github.com/en/rest/billing#get-github-advanced-security-active-committers-for-an-organization +func (s *BillingService) GetAdvancedSecurityActiveCommittersOrg(ctx context.Context, org string) (*ActiveCommitters, *Response, error) { + u := fmt.Sprintf("orgs/%v/settings/billing/advanced-security", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + activeOrgCommitters := new(ActiveCommitters) + resp, err := s.client.Do(ctx, req, activeOrgCommitters) + if err != nil { + return nil, resp, err + } + + return activeOrgCommitters, resp, nil +} + +// GetActionsBillingUser returns the summary of the free and paid GitHub Actions minutes used for a user. +// +// GitHub API docs: https://docs.github.com/en/rest/billing#get-github-actions-billing-for-a-user +func (s *BillingService) GetActionsBillingUser(ctx context.Context, user string) (*ActionBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/actions", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsUserBilling := new(ActionBilling) + resp, err := s.client.Do(ctx, req, actionsUserBilling) + if err != nil { + return nil, resp, err + } + + return actionsUserBilling, resp, nil +} + +// GetPackagesBillingUser returns the free and paid storage used for GitHub Packages in gigabytes for a user. +// +// GitHub API docs: https://docs.github.com/en/rest/billing#get-github-packages-billing-for-a-user +func (s *BillingService) GetPackagesBillingUser(ctx context.Context, user string) (*PackageBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/packages", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + packagesUserBilling := new(PackageBilling) + resp, err := s.client.Do(ctx, req, packagesUserBilling) + if err != nil { + return nil, resp, err + } + + return packagesUserBilling, resp, nil +} + +// GetStorageBillingUser returns the estimated paid and estimated total storage used for GitHub Actions +// and GitHub Packages in gigabytes for a user. +// +// GitHub API docs: https://docs.github.com/en/rest/billing#get-shared-storage-billing-for-a-user +func (s *BillingService) GetStorageBillingUser(ctx context.Context, user string) (*StorageBilling, *Response, error) { + u := fmt.Sprintf("users/%v/settings/billing/shared-storage", user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + storageUserBilling := new(StorageBilling) + resp, err := s.client.Do(ctx, req, storageUserBilling) + if err != nil { + return nil, resp, err + } + + return storageUserBilling, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/checks.go b/vendor/github.com/google/go-github/v45/github/checks.go new file mode 100644 index 0000000000..12d08530ca --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/checks.go @@ -0,0 +1,451 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ChecksService provides access to the Checks API in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/ +type ChecksService service + +// CheckRun represents a GitHub check run on a repository associated with a GitHub app. +type CheckRun struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + ExternalID *string `json:"external_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DetailsURL *string `json:"details_url,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` + Output *CheckRunOutput `json:"output,omitempty"` + Name *string `json:"name,omitempty"` + CheckSuite *CheckSuite `json:"check_suite,omitempty"` + App *App `json:"app,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` +} + +// CheckRunOutput represents the output of a CheckRun. +type CheckRunOutput struct { + Title *string `json:"title,omitempty"` + Summary *string `json:"summary,omitempty"` + Text *string `json:"text,omitempty"` + AnnotationsCount *int `json:"annotations_count,omitempty"` + AnnotationsURL *string `json:"annotations_url,omitempty"` + Annotations []*CheckRunAnnotation `json:"annotations,omitempty"` + Images []*CheckRunImage `json:"images,omitempty"` +} + +// CheckRunAnnotation represents an annotation object for a CheckRun output. +type CheckRunAnnotation struct { + Path *string `json:"path,omitempty"` + StartLine *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` + AnnotationLevel *string `json:"annotation_level,omitempty"` + Message *string `json:"message,omitempty"` + Title *string `json:"title,omitempty"` + RawDetails *string `json:"raw_details,omitempty"` +} + +// CheckRunImage represents an image object for a CheckRun output. +type CheckRunImage struct { + Alt *string `json:"alt,omitempty"` + ImageURL *string `json:"image_url,omitempty"` + Caption *string `json:"caption,omitempty"` +} + +// CheckSuite represents a suite of check runs. +type CheckSuite struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + URL *string `json:"url,omitempty"` + BeforeSHA *string `json:"before,omitempty"` + AfterSHA *string `json:"after,omitempty"` + Status *string `json:"status,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + App *App `json:"app,omitempty"` + Repository *Repository `json:"repository,omitempty"` + PullRequests []*PullRequest `json:"pull_requests,omitempty"` + + // The following fields are only populated by Webhook events. + HeadCommit *Commit `json:"head_commit,omitempty"` +} + +func (c CheckRun) String() string { + return Stringify(c) +} + +func (c CheckSuite) String() string { + return Stringify(c) +} + +// GetCheckRun gets a check-run for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/runs#get-a-check-run +func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*CheckRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkRun := new(CheckRun) + resp, err := s.client.Do(ctx, req, checkRun) + if err != nil { + return nil, resp, err + } + + return checkRun, resp, nil +} + +// GetCheckSuite gets a single check suite. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/suites#get-a-check-suite +func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*CheckSuite, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/%v", owner, repo, checkSuiteID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkSuite := new(CheckSuite) + resp, err := s.client.Do(ctx, req, checkSuite) + if err != nil { + return nil, resp, err + } + + return checkSuite, resp, nil +} + +// CreateCheckRunOptions sets up parameters needed to create a CheckRun. +type CreateCheckRunOptions struct { + Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) + HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.) + DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) + ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) + Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) + Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "skipped", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) + StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.) + CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) + Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) + Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) +} + +// CheckRunAction exposes further actions the integrator can perform, which a user may trigger. +type CheckRunAction struct { + Label string `json:"label"` // The text to be displayed on a button in the web UI. The maximum size is 20 characters. (Required.) + Description string `json:"description"` // A short explanation of what this action would do. The maximum size is 40 characters. (Required.) + Identifier string `json:"identifier"` // A reference for the action on the integrator's system. The maximum size is 20 characters. (Required.) +} + +// CreateCheckRun creates a check run for repository. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/runs#create-a-check-run +func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opts CreateCheckRunOptions) (*CheckRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkRun := new(CheckRun) + resp, err := s.client.Do(ctx, req, checkRun) + if err != nil { + return nil, resp, err + } + + return checkRun, resp, nil +} + +// UpdateCheckRunOptions sets up parameters needed to update a CheckRun. +type UpdateCheckRunOptions struct { + Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.) + DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.) + ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.) + Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.) + Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "skipped", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".) + CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.) + Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional) + Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.) +} + +// UpdateCheckRun updates a check run for a specific commit in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/runs#update-a-check-run +func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opts UpdateCheckRunOptions) (*CheckRun, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkRun := new(CheckRun) + resp, err := s.client.Do(ctx, req, checkRun) + if err != nil { + return nil, resp, err + } + + return checkRun, resp, nil +} + +// ListCheckRunAnnotations lists the annotations for a check run. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/runs#list-check-run-annotations +func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opts *ListOptions) ([]*CheckRunAnnotation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkRunAnnotations []*CheckRunAnnotation + resp, err := s.client.Do(ctx, req, &checkRunAnnotations) + if err != nil { + return nil, resp, err + } + + return checkRunAnnotations, resp, nil +} + +// ListCheckRunsOptions represents parameters to list check runs. +type ListCheckRunsOptions struct { + CheckName *string `url:"check_name,omitempty"` // Returns check runs with the specified name. + Status *string `url:"status,omitempty"` // Returns check runs with the specified status. Can be one of "queued", "in_progress", or "completed". + Filter *string `url:"filter,omitempty"` // Filters check runs by their completed_at timestamp. Can be one of "latest" (returning the most recent check runs) or "all". Default: "latest" + AppID *int64 `url:"app_id,omitempty"` // Filters check runs by GitHub App ID. + + ListOptions +} + +// ListCheckRunsResults represents the result of a check run list. +type ListCheckRunsResults struct { + Total *int `json:"total_count,omitempty"` + CheckRuns []*CheckRun `json:"check_runs,omitempty"` +} + +// ListCheckRunsForRef lists check runs for a specific ref. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/runs#list-check-runs-for-a-git-reference +func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkRunResults *ListCheckRunsResults + resp, err := s.client.Do(ctx, req, &checkRunResults) + if err != nil { + return nil, resp, err + } + + return checkRunResults, resp, nil +} + +// ListCheckRunsCheckSuite lists check runs for a check suite. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/runs#list-check-runs-in-a-check-suite +func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/%v/check-runs", owner, repo, checkSuiteID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkRunResults *ListCheckRunsResults + resp, err := s.client.Do(ctx, req, &checkRunResults) + if err != nil { + return nil, resp, err + } + + return checkRunResults, resp, nil +} + +// ReRequestCheckRun triggers GitHub to rerequest an existing check run. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/runs#rerequest-a-check-run +func (s *ChecksService) ReRequestCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-runs/%v/rerequest", owner, repo, checkRunID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ListCheckSuiteOptions represents parameters to list check suites. +type ListCheckSuiteOptions struct { + CheckName *string `url:"check_name,omitempty"` // Filters checks suites by the name of the check run. + AppID *int `url:"app_id,omitempty"` // Filters check suites by GitHub App id. + + ListOptions +} + +// ListCheckSuiteResults represents the result of a check run list. +type ListCheckSuiteResults struct { + Total *int `json:"total_count,omitempty"` + CheckSuites []*CheckSuite `json:"check_suites,omitempty"` +} + +// ListCheckSuitesForRef lists check suite for a specific ref. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/suites#list-check-suites-for-a-git-reference +func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkSuiteResults *ListCheckSuiteResults + resp, err := s.client.Do(ctx, req, &checkSuiteResults) + if err != nil { + return nil, resp, err + } + + return checkSuiteResults, resp, nil +} + +// AutoTriggerCheck enables or disables automatic creation of CheckSuite events upon pushes to the repository. +type AutoTriggerCheck struct { + AppID *int64 `json:"app_id,omitempty"` // The id of the GitHub App. (Required.) + Setting *bool `json:"setting,omitempty"` // Set to "true" to enable automatic creation of CheckSuite events upon pushes to the repository, or "false" to disable them. Default: "true" (Required.) +} + +// CheckSuitePreferenceOptions set options for check suite preferences for a repository. +type CheckSuitePreferenceOptions struct { + AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. +} + +// CheckSuitePreferenceResults represents the results of the preference set operation. +type CheckSuitePreferenceResults struct { + Preferences *PreferenceList `json:"preferences,omitempty"` + Repository *Repository `json:"repository,omitempty"` +} + +// PreferenceList represents a list of auto trigger checks for repository +type PreferenceList struct { + AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository. +} + +// SetCheckSuitePreferences changes the default automatic flow when creating check suites. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/suites#update-repository-preferences-for-check-suites +func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opts CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + var checkSuitePrefResults *CheckSuitePreferenceResults + resp, err := s.client.Do(ctx, req, &checkSuitePrefResults) + if err != nil { + return nil, resp, err + } + + return checkSuitePrefResults, resp, nil +} + +// CreateCheckSuiteOptions sets up parameters to manually create a check suites +type CreateCheckSuiteOptions struct { + HeadSHA string `json:"head_sha"` // The sha of the head commit. (Required.) + HeadBranch *string `json:"head_branch,omitempty"` // The name of the head branch where the code changes are implemented. +} + +// CreateCheckSuite manually creates a check suite for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/suites#create-a-check-suite +func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opts CreateCheckSuiteOptions) (*CheckSuite, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + checkSuite := new(CheckSuite) + resp, err := s.client.Do(ctx, req, checkSuite) + if err != nil { + return nil, resp, err + } + + return checkSuite, resp, nil +} + +// ReRequestCheckSuite triggers GitHub to rerequest an existing check suite, without pushing new code to a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/checks/suites#rerequest-a-check-suite +func (s *ChecksService) ReRequestCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/check-suites/%v/rerequest", owner, repo, checkSuiteID) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", mediaTypeCheckRunsPreview) + + resp, err := s.client.Do(ctx, req, nil) + return resp, err +} diff --git a/vendor/github.com/google/go-github/v45/github/code-scanning.go b/vendor/github.com/google/go-github/v45/github/code-scanning.go new file mode 100644 index 0000000000..df8ed86b51 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/code-scanning.go @@ -0,0 +1,334 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strconv" + "strings" +) + +// CodeScanningService handles communication with the code scanning related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning +type CodeScanningService service + +// Rule represents the complete details of GitHub Code Scanning alert type. +type Rule struct { + ID *string `json:"id,omitempty"` + Severity *string `json:"severity,omitempty"` + Description *string `json:"description,omitempty"` + Name *string `json:"name,omitempty"` + SecuritySeverityLevel *string `json:"security_severity_level,omitempty"` + FullDescription *string `json:"full_description,omitempty"` + Tags []string `json:"tags,omitempty"` + Help *string `json:"help,omitempty"` +} + +// Location represents the exact location of the GitHub Code Scanning Alert in the scanned project. +type Location struct { + Path *string `json:"path,omitempty"` + StartLine *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` +} + +// Message is a part of MostRecentInstance struct which provides the appropriate message when any action is performed on the analysis object. +type Message struct { + Text *string `json:"text,omitempty"` +} + +// MostRecentInstance provides details of the most recent instance of this alert for the default branch or for the specified Git reference. +type MostRecentInstance struct { + Ref *string `json:"ref,omitempty"` + AnalysisKey *string `json:"analysis_key,omitempty"` + Environment *string `json:"environment,omitempty"` + State *string `json:"state,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + Message *Message `json:"message,omitempty"` + Location *Location `json:"location,omitempty"` + Classifications []string `json:"classifications,omitempty"` +} + +// Tool represents the tool used to generate a GitHub Code Scanning Alert. +type Tool struct { + Name *string `json:"name,omitempty"` + GUID *string `json:"guid,omitempty"` + Version *string `json:"version,omitempty"` +} + +// Alert represents an individual GitHub Code Scanning Alert on a single repository. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning +type Alert struct { + Number *int `json:"number,omitempty"` + Repository *Repository `json:"repository,omitempty"` + RuleID *string `json:"rule_id,omitempty"` + RuleSeverity *string `json:"rule_severity,omitempty"` + RuleDescription *string `json:"rule_description,omitempty"` + Rule *Rule `json:"rule,omitempty"` + Tool *Tool `json:"tool,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + FixedAt *Timestamp `json:"fixed_at,omitempty"` + State *string `json:"state,omitempty"` + ClosedBy *User `json:"closed_by,omitempty"` + ClosedAt *Timestamp `json:"closed_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + MostRecentInstance *MostRecentInstance `json:"most_recent_instance,omitempty"` + Instances []*MostRecentInstance `json:"instances,omitempty"` + DismissedBy *User `json:"dismissed_by,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` + DismissedReason *string `json:"dismissed_reason,omitempty"` + InstancesURL *string `json:"instances_url,omitempty"` +} + +// ID returns the ID associated with an alert. It is the number at the end of the security alert's URL. +func (a *Alert) ID() int64 { + if a == nil { + return 0 + } + + s := a.GetHTMLURL() + + // Check for an ID to parse at the end of the url + if i := strings.LastIndex(s, "/"); i >= 0 { + s = s[i+1:] + } + + // Return the alert ID as a 64-bit integer. Unable to convert or out of range returns 0. + id, err := strconv.ParseInt(s, 10, 64) + if err != nil { + return 0 + } + + return id +} + +// AlertListOptions specifies optional parameters to the CodeScanningService.ListAlerts +// method. +type AlertListOptions struct { + // State of the code scanning alerts to list. Set to closed to list only closed code scanning alerts. Default: open + State string `url:"state,omitempty"` + + // Return code scanning alerts for a specific branch reference. The ref must be formatted as heads/. + Ref string `url:"ref,omitempty"` + + ListOptions +} + +// AnalysesListOptions specifies optional parameters to the CodeScanningService.ListAnalysesForRepo method. +type AnalysesListOptions struct { + // Return code scanning analyses belonging to the same SARIF upload. + SarifID *string `url:"sarif_id,omitempty"` + + // Return code scanning analyses for a specific branch reference. The ref can be formatted as refs/heads/ or simply . + Ref *string `url:"ref,omitempty"` + + ListOptions +} + +// ScanningAnalysis represents an individual GitHub Code Scanning ScanningAnalysis on a single repository. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning +type ScanningAnalysis struct { + ID *int64 `json:"id,omitempty"` + Ref *string `json:"ref,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + AnalysisKey *string `json:"analysis_key,omitempty"` + Environment *string `json:"environment,omitempty"` + Error *string `json:"error,omitempty"` + Category *string `json:"category,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + ResultsCount *int `json:"results_count,omitempty"` + RulesCount *int `json:"rules_count,omitempty"` + URL *string `json:"url,omitempty"` + SarifID *string `json:"sarif_id,omitempty"` + Tool *Tool `json:"tool,omitempty"` + Deletable *bool `json:"deletable,omitempty"` + Warning *string `json:"warning,omitempty"` +} + +// SarifAnalysis specifies the results of a code scanning job. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning +type SarifAnalysis struct { + CommitSHA *string `json:"commit_sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Sarif *string `json:"sarif,omitempty"` + CheckoutURI *string `json:"checkout_uri,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + ToolName *string `json:"tool_name,omitempty"` +} + +// SarifID identifies a sarif analysis upload. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning +type SarifID struct { + ID *string `json:"id,omitempty"` + URL *string `json:"url,omitempty"` +} + +// ListAlertsForOrg lists code scanning alerts for an org. +// +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-alerts-for-an-organization +func (s *CodeScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *AlertListOptions) ([]*Alert, *Response, error) { + u := fmt.Sprintf("orgs/%v/code-scanning/alerts", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*Alert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// ListAlertsForRepo lists code scanning alerts for a repository. +// +// Lists all open code scanning alerts for the default branch (usually master) and protected branches in a repository. +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-alerts-for-a-repository +func (s *CodeScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *AlertListOptions) ([]*Alert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*Alert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// GetAlert gets a single code scanning alert for a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security alert_id is the number at the end of the security alert's URL. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning#get-a-code-scanning-alert +func (s *CodeScanningService) GetAlert(ctx context.Context, owner, repo string, id int64) (*Alert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/alerts/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + a := new(Alert) + resp, err := s.client.Do(ctx, req, a) + if err != nil { + return nil, resp, err + } + + return a, resp, nil +} + +// UploadSarif uploads the result of code scanning job to GitHub. +// +// For the parameter sarif, you must first compress your SARIF file using gzip and then translate the contents of the file into a Base64 encoding string. +// You must use an access token with the security_events scope to use this endpoint. GitHub Apps must have the security_events +// write permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning#upload-an-analysis-as-sarif-data +func (s *CodeScanningService) UploadSarif(ctx context.Context, owner, repo string, sarif *SarifAnalysis) (*SarifID, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/sarifs", owner, repo) + + req, err := s.client.NewRequest("POST", u, sarif) + if err != nil { + return nil, nil, err + } + + sarifID := new(SarifID) + resp, err := s.client.Do(ctx, req, sarifID) + if err != nil { + return nil, resp, err + } + + return sarifID, resp, nil +} + +// ListAnalysesForRepo lists code scanning analyses for a repository. +// +// Lists the details of all code scanning analyses for a repository, starting with the most recent. +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning#list-code-scanning-analyses-for-a-repository +func (s *CodeScanningService) ListAnalysesForRepo(ctx context.Context, owner, repo string, opts *AnalysesListOptions) ([]*ScanningAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var analyses []*ScanningAnalysis + resp, err := s.client.Do(ctx, req, &analyses) + if err != nil { + return nil, resp, err + } + + return analyses, resp, nil +} + +// GetAnalysis gets a single code scanning analysis for a repository. +// +// You must use an access token with the security_events scope to use this endpoint. +// GitHub Apps must have the security_events read permission to use this endpoint. +// +// The security analysis_id is the ID of the analysis, as returned from the ListAnalysesForRepo operation. +// +// GitHub API docs: https://docs.github.com/en/rest/code-scanning#get-a-code-scanning-analysis-for-a-repository +func (s *CodeScanningService) GetAnalysis(ctx context.Context, owner, repo string, id int64) (*ScanningAnalysis, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/code-scanning/analyses/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + analysis := new(ScanningAnalysis) + resp, err := s.client.Do(ctx, req, analysis) + if err != nil { + return nil, resp, err + } + + return analysis, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/dependabot.go b/vendor/github.com/google/go-github/v45/github/dependabot.go new file mode 100644 index 0000000000..07e68b506a --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/dependabot.go @@ -0,0 +1,12 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// DependabotService handles communication with the Dependabot related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/ +type DependabotService service diff --git a/vendor/github.com/google/go-github/v45/github/dependabot_secrets.go b/vendor/github.com/google/go-github/v45/github/dependabot_secrets.go new file mode 100644 index 0000000000..f51f3396bd --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/dependabot_secrets.go @@ -0,0 +1,228 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +func (s *DependabotService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + pubKey := new(PublicKey) + resp, err := s.client.Do(ctx, req, pubKey) + if err != nil { + return nil, resp, err + } + + return pubKey, resp, nil +} + +// GetRepoPublicKey gets a public key that should be used for Dependabot secret encryption. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#get-a-repository-public-key +func (s *DependabotService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/public-key", owner, repo) + return s.getPublicKey(ctx, url) +} + +// GetOrgPublicKey gets a public key that should be used for Dependabot secret encryption. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#get-an-organization-public-key +func (s *DependabotService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/public-key", org) + return s.getPublicKey(ctx, url) +} + +func (s *DependabotService) listSecrets(ctx context.Context, url string, opts *ListOptions) (*Secrets, *Response, error) { + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + secrets := new(Secrets) + resp, err := s.client.Do(ctx, req, &secrets) + if err != nil { + return nil, resp, err + } + + return secrets, resp, nil +} + +// ListRepoSecrets lists all Dependabot secrets available in a repository +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#list-repository-secrets +func (s *DependabotService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets", owner, repo) + return s.listSecrets(ctx, url, opts) +} + +// ListOrgSecrets lists all Dependabot secrets available in an organization +// without revealing their encrypted values. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#list-organization-secrets +func (s *DependabotService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets", org) + return s.listSecrets(ctx, url, opts) +} + +func (s *DependabotService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + secret := new(Secret) + resp, err := s.client.Do(ctx, req, secret) + if err != nil { + return nil, resp, err + } + + return secret, resp, nil +} + +// GetRepoSecret gets a single repository Dependabot secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#get-a-repository-secret +func (s *DependabotService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, name) + return s.getSecret(ctx, url) +} + +// GetOrgSecret gets a single organization Dependabot secret without revealing its encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#get-an-organization-secret +func (s *DependabotService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, name) + return s.getSecret(ctx, url) +} + +func (s *DependabotService) putSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { + req, err := s.client.NewRequest("PUT", url, eSecret) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// CreateOrUpdateRepoSecret creates or updates a repository Dependabot secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#create-or-update-a-repository-secret +func (s *DependabotService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +// CreateOrUpdateOrgSecret creates or updates an organization Dependabot secret with an encrypted value. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#create-or-update-an-organization-secret +func (s *DependabotService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, eSecret.Name) + return s.putSecret(ctx, url, eSecret) +} + +func (s *DependabotService) deleteSecret(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteRepoSecret deletes a Dependabot secret in a repository using the secret name. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#delete-a-repository-secret +func (s *DependabotService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/dependabot/secrets/%v", owner, repo, name) + return s.deleteSecret(ctx, url) +} + +// DeleteOrgSecret deletes a Dependabot secret in an organization using the secret name. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#delete-an-organization-secret +func (s *DependabotService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v", org, name) + return s.deleteSecret(ctx, url) +} + +// ListSelectedReposForOrgSecret lists all repositories that have access to a Dependabot secret. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#list-selected-repositories-for-an-organization-secret +func (s *DependabotService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories", org, name) + u, err := addOptions(url, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(SelectedReposList) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// SetSelectedReposForOrgSecret sets the repositories that have access to a Dependabot secret. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#set-selected-repositories-for-an-organization-secret +func (s *DependabotService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories", org, name) + type repoIDs struct { + SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` + } + + req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddSelectedRepoToOrgSecret adds a repository to an organization Dependabot secret. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#add-selected-repository-to-an-organization-secret +func (s *DependabotService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories/%v", org, name, *repo.ID) + req, err := s.client.NewRequest("PUT", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveSelectedRepoFromOrgSecret removes a repository from an organization Dependabot secret. +// +// GitHub API docs: https://docs.github.com/en/rest/dependabot/secrets#remove-selected-repository-from-an-organization-secret +func (s *DependabotService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { + url := fmt.Sprintf("orgs/%v/dependabot/secrets/%v/repositories/%v", org, name, *repo.ID) + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/doc.go b/vendor/github.com/google/go-github/v45/github/doc.go new file mode 100644 index 0000000000..38cda12b2b --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/doc.go @@ -0,0 +1,213 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package github provides a client for using the GitHub API. + +Usage: + + import "github.com/google/go-github/v45/github" // with go modules enabled (GO111MODULE=on or outside GOPATH) + import "github.com/google/go-github/github" // with go modules disabled + +Construct a new GitHub client, then use the various services on the client to +access different parts of the GitHub API. For example: + + client := github.NewClient(nil) + + // list all organizations for user "willnorris" + orgs, _, err := client.Organizations.List(ctx, "willnorris", nil) + +Some API methods have optional parameters that can be passed. For example: + + client := github.NewClient(nil) + + // list public repositories for org "github" + opt := &github.RepositoryListByOrgOptions{Type: "public"} + repos, _, err := client.Repositories.ListByOrg(ctx, "github", opt) + +The services of a client divide the API into logical chunks and correspond to +the structure of the GitHub API documentation at +https://docs.github.com/en/rest . + +NOTE: Using the https://godoc.org/context package, one can easily +pass cancelation signals and deadlines to various services of the client for +handling a request. In case there is no context available, then context.Background() +can be used as a starting point. + +For more sample code snippets, head over to the https://github.com/google/go-github/tree/master/example directory. + +Authentication + +The go-github library does not directly handle authentication. Instead, when +creating a new client, pass an http.Client that can handle authentication for +you. The easiest and recommended way to do this is using the golang.org/x/oauth2 +library, but you can always use any other library that provides an http.Client. +If you have an OAuth2 access token (for example, a personal API token), you can +use it with the oauth2 library using: + + import "golang.org/x/oauth2" + + func main() { + ctx := context.Background() + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: "... your access token ..."}, + ) + tc := oauth2.NewClient(ctx, ts) + + client := github.NewClient(tc) + + // list all repositories for the authenticated user + repos, _, err := client.Repositories.List(ctx, "", nil) + } + +Note that when using an authenticated Client, all calls made by the client will +include the specified OAuth token. Therefore, authenticated clients should +almost never be shared between different users. + +See the oauth2 docs for complete instructions on using that library. + +For API methods that require HTTP Basic Authentication, use the +BasicAuthTransport. + +GitHub Apps authentication can be provided by the +https://github.com/bradleyfalzon/ghinstallation package. +It supports both authentication as an installation, using an installation access token, +and as an app, using a JWT. + +To authenticate as an installation: + + import "github.com/bradleyfalzon/ghinstallation" + + func main() { + // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99. + itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem") + if err != nil { + // Handle error. + } + + // Use installation transport with client + client := github.NewClient(&http.Client{Transport: itr}) + + // Use client... + } + +To authenticate as an app, using a JWT: + + import "github.com/bradleyfalzon/ghinstallation" + + func main() { + // Wrap the shared transport for use with the application ID 1. + atr, err := ghinstallation.NewAppsTransportKeyFromFile(http.DefaultTransport, 1, "2016-10-19.private-key.pem") + if err != nil { + // Handle error. + } + + // Use app transport with client + client := github.NewClient(&http.Client{Transport: atr}) + + // Use client... + } + +Rate Limiting + +GitHub imposes a rate limit on all API clients. Unauthenticated clients are +limited to 60 requests per hour, while authenticated clients can make up to +5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated +clients are limited to 10 requests per minute, while authenticated clients +can make up to 30 requests per minute. To receive the higher rate limit when +making calls that are not issued on behalf of a user, +use UnauthenticatedRateLimitedTransport. + +The returned Response.Rate value contains the rate limit information +from the most recent API call. If a recent enough response isn't +available, you can use RateLimits to fetch the most up-to-date rate +limit data for the client. + +To detect an API rate limit error, you can check if its type is *github.RateLimitError. +For secondary rate limits, you can check if its type is *github.AbuseRateLimitError: + + repos, _, err := client.Repositories.List(ctx, "", nil) + if _, ok := err.(*github.RateLimitError); ok { + log.Println("hit rate limit") + } + if _, ok := err.(*github.AbuseRateLimitError); ok { + log.Println("hit secondary rate limit") + } + +Learn more about GitHub rate limiting at +https://docs.github.com/en/rest/rate-limit . + +Accepted Status + +Some endpoints may return a 202 Accepted status code, meaning that the +information required is not yet ready and was scheduled to be gathered on +the GitHub side. Methods known to behave like this are documented specifying +this behavior. + +To detect this condition of error, you can check if its type is +*github.AcceptedError: + + stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo) + if _, ok := err.(*github.AcceptedError); ok { + log.Println("scheduled on GitHub side") + } + +Conditional Requests + +The GitHub API has good support for conditional requests which will help +prevent you from burning through your rate limit, as well as help speed up your +application. go-github does not handle conditional requests directly, but is +instead designed to work with a caching http.Transport. We recommend using +https://github.com/gregjones/httpcache for that. + +Learn more about GitHub conditional requests at +https://docs.github.com/en/rest/overview/resources-in-the-rest-api#conditional-requests. + +Creating and Updating Resources + +All structs for GitHub resources use pointer values for all non-repeated fields. +This allows distinguishing between unset fields and those set to a zero-value. +Helper functions have been provided to easily create these pointers for string, +bool, and int values. For example: + + // create a new private repository named "foo" + repo := &github.Repository{ + Name: github.String("foo"), + Private: github.Bool(true), + } + client.Repositories.Create(ctx, "", repo) + +Users who have worked with protocol buffers should find this pattern familiar. + +Pagination + +All requests for resource collections (repos, pull requests, issues, etc.) +support pagination. Pagination options are described in the +github.ListOptions struct and passed to the list methods directly or as an +embedded type of a more specific list options struct (for example +github.PullRequestListOptions). Pages information is available via the +github.Response struct. + + client := github.NewClient(nil) + + opt := &github.RepositoryListByOrgOptions{ + ListOptions: github.ListOptions{PerPage: 10}, + } + // get all pages of results + var allRepos []*github.Repository + for { + repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt) + if err != nil { + return err + } + allRepos = append(allRepos, repos...) + if resp.NextPage == 0 { + break + } + opt.Page = resp.NextPage + } + +*/ +package github diff --git a/vendor/github.com/google/go-github/v45/github/enterprise.go b/vendor/github.com/google/go-github/v45/github/enterprise.go new file mode 100644 index 0000000000..1c9b069566 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/enterprise.go @@ -0,0 +1,12 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// EnterpriseService provides access to the enterprise related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/enterprise-admin/ +type EnterpriseService service diff --git a/vendor/github.com/google/go-github/v45/github/enterprise_actions_runners.go b/vendor/github.com/google/go-github/v45/github/enterprise_actions_runners.go new file mode 100644 index 0000000000..f2ba166360 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/enterprise_actions_runners.go @@ -0,0 +1,69 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// CreateRegistrationToken creates a token that can be used to add a self-hosted runner. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#create-a-registration-token-for-an-enterprise +func (s *EnterpriseService) CreateRegistrationToken(ctx context.Context, enterprise string) (*RegistrationToken, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/registration-token", enterprise) + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + registrationToken := new(RegistrationToken) + resp, err := s.client.Do(ctx, req, registrationToken) + if err != nil { + return nil, resp, err + } + + return registrationToken, resp, nil +} + +// ListRunners lists all the self-hosted runners for a enterprise. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#list-self-hosted-runners-for-an-enterprise +func (s *EnterpriseService) ListRunners(ctx context.Context, enterprise string, opts *ListOptions) (*Runners, *Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + runners := &Runners{} + resp, err := s.client.Do(ctx, req, &runners) + if err != nil { + return nil, resp, err + } + + return runners, resp, nil +} + +// RemoveRunner forces the removal of a self-hosted runner from an enterprise using the runner id. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/self-hosted-runners#delete-a-self-hosted-runner-from-an-enterprise +func (s *EnterpriseService) RemoveRunner(ctx context.Context, enterprise string, runnerID int64) (*Response, error) { + u := fmt.Sprintf("enterprises/%v/actions/runners/%v", enterprise, runnerID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/enterprise_audit_log.go b/vendor/github.com/google/go-github/v45/github/enterprise_audit_log.go new file mode 100644 index 0000000000..4064867338 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/enterprise_audit_log.go @@ -0,0 +1,35 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAuditLog gets the audit-log entries for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/enterprise-admin/audit-log#get-the-audit-log-for-an-enterprise +func (s *EnterpriseService) GetAuditLog(ctx context.Context, enterprise string, opts *GetAuditLogOptions) ([]*AuditEntry, *Response, error) { + u := fmt.Sprintf("enterprises/%v/audit-log", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var auditEntries []*AuditEntry + resp, err := s.client.Do(ctx, req, &auditEntries) + if err != nil { + return nil, resp, err + } + + return auditEntries, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/event.go b/vendor/github.com/google/go-github/v45/github/event.go new file mode 100644 index 0000000000..5a052de09c --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/event.go @@ -0,0 +1,158 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "encoding/json" + "time" +) + +// Event represents a GitHub event. +type Event struct { + Type *string `json:"type,omitempty"` + Public *bool `json:"public,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` + Repo *Repository `json:"repo,omitempty"` + Actor *User `json:"actor,omitempty"` + Org *Organization `json:"org,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + ID *string `json:"id,omitempty"` +} + +func (e Event) String() string { + return Stringify(e) +} + +// ParsePayload parses the event payload. For recognized event types, +// a value of the corresponding struct type will be returned. +func (e *Event) ParsePayload() (payload interface{}, err error) { + switch *e.Type { + case "BranchProtectionRuleEvent": + payload = &BranchProtectionRuleEvent{} + case "CheckRunEvent": + payload = &CheckRunEvent{} + case "CheckSuiteEvent": + payload = &CheckSuiteEvent{} + case "CommitCommentEvent": + payload = &CommitCommentEvent{} + case "ContentReferenceEvent": + payload = &ContentReferenceEvent{} + case "CreateEvent": + payload = &CreateEvent{} + case "DeleteEvent": + payload = &DeleteEvent{} + case "DeployKeyEvent": + payload = &DeployKeyEvent{} + case "DeploymentEvent": + payload = &DeploymentEvent{} + case "DeploymentStatusEvent": + payload = &DeploymentStatusEvent{} + case "DiscussionEvent": + payload = &DiscussionEvent{} + case "ForkEvent": + payload = &ForkEvent{} + case "GitHubAppAuthorizationEvent": + payload = &GitHubAppAuthorizationEvent{} + case "GollumEvent": + payload = &GollumEvent{} + case "InstallationEvent": + payload = &InstallationEvent{} + case "InstallationRepositoriesEvent": + payload = &InstallationRepositoriesEvent{} + case "IssueCommentEvent": + payload = &IssueCommentEvent{} + case "IssuesEvent": + payload = &IssuesEvent{} + case "LabelEvent": + payload = &LabelEvent{} + case "MarketplacePurchaseEvent": + payload = &MarketplacePurchaseEvent{} + case "MemberEvent": + payload = &MemberEvent{} + case "MembershipEvent": + payload = &MembershipEvent{} + case "MetaEvent": + payload = &MetaEvent{} + case "MilestoneEvent": + payload = &MilestoneEvent{} + case "OrganizationEvent": + payload = &OrganizationEvent{} + case "OrgBlockEvent": + payload = &OrgBlockEvent{} + case "PackageEvent": + payload = &PackageEvent{} + case "PageBuildEvent": + payload = &PageBuildEvent{} + case "PingEvent": + payload = &PingEvent{} + case "ProjectEvent": + payload = &ProjectEvent{} + case "ProjectCardEvent": + payload = &ProjectCardEvent{} + case "ProjectColumnEvent": + payload = &ProjectColumnEvent{} + case "PublicEvent": + payload = &PublicEvent{} + case "PullRequestEvent": + payload = &PullRequestEvent{} + case "PullRequestReviewEvent": + payload = &PullRequestReviewEvent{} + case "PullRequestReviewCommentEvent": + payload = &PullRequestReviewCommentEvent{} + case "PullRequestReviewThreadEvent": + payload = &PullRequestReviewThreadEvent{} + case "PullRequestTargetEvent": + payload = &PullRequestTargetEvent{} + case "PushEvent": + payload = &PushEvent{} + case "ReleaseEvent": + payload = &ReleaseEvent{} + case "RepositoryEvent": + payload = &RepositoryEvent{} + case "RepositoryDispatchEvent": + payload = &RepositoryDispatchEvent{} + case "RepositoryImportEvent": + payload = &RepositoryImportEvent{} + case "RepositoryVulnerabilityAlertEvent": + payload = &RepositoryVulnerabilityAlertEvent{} + case "SecretScanningAlertEvent": + payload = &SecretScanningAlertEvent{} + case "StarEvent": + payload = &StarEvent{} + case "StatusEvent": + payload = &StatusEvent{} + case "TeamEvent": + payload = &TeamEvent{} + case "TeamAddEvent": + payload = &TeamAddEvent{} + case "UserEvent": + payload = &UserEvent{} + case "WatchEvent": + payload = &WatchEvent{} + case "WorkflowDispatchEvent": + payload = &WorkflowDispatchEvent{} + case "WorkflowJobEvent": + payload = &WorkflowJobEvent{} + case "WorkflowRunEvent": + payload = &WorkflowRunEvent{} + } + err = json.Unmarshal(*e.RawPayload, &payload) + return payload, err +} + +// Payload returns the parsed event payload. For recognized event types, +// a value of the corresponding struct type will be returned. +// +// Deprecated: Use ParsePayload instead, which returns an error +// rather than panics if JSON unmarshaling raw payload fails. +func (e *Event) Payload() (payload interface{}) { + var err error + payload, err = e.ParsePayload() + if err != nil { + panic(err) + } + return payload +} diff --git a/vendor/github.com/google/go-github/v45/github/event_types.go b/vendor/github.com/google/go-github/v45/github/event_types.go new file mode 100644 index 0000000000..c80a835f6b --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/event_types.go @@ -0,0 +1,1351 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// These event types are shared between the Events API and used as Webhook payloads. + +package github + +import "encoding/json" + +// RequestedAction is included in a CheckRunEvent when a user has invoked an action, +// i.e. when the CheckRunEvent's Action field is "requested_action". +type RequestedAction struct { + Identifier string `json:"identifier"` // The integrator reference of the action requested by the user. +} + +// BranchProtectionRuleEvent triggered when a check suite is "created", "edited", or "deleted". +// The Webhook event name is "branch_protection_rule". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#branch_protection_rule +type BranchProtectionRuleEvent struct { + Action *string `json:"action,omitempty"` + Rule *BranchProtectionRule `json:"rule,omitempty"` + Changes *ProtectionChanges `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CheckRunEvent is triggered when a check run is "created", "completed", or "rerequested". +// The Webhook event name is "check_run". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#check_run +type CheckRunEvent struct { + CheckRun *CheckRun `json:"check_run,omitempty"` + // The action performed. Possible values are: "created", "completed", "rerequested" or "requested_action". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The action requested by the user. Populated when the Action is "requested_action". + RequestedAction *RequestedAction `json:"requested_action,omitempty"` // +} + +// CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "rerequested". +// The Webhook event name is "check_suite". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#check_suite +type CheckSuiteEvent struct { + CheckSuite *CheckSuite `json:"check_suite,omitempty"` + // The action performed. Possible values are: "completed", "requested" or "rerequested". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CommitCommentEvent is triggered when a commit comment is created. +// The Webhook event name is "commit_comment". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#commit_comment +type CommitCommentEvent struct { + Comment *RepositoryComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ContentReferenceEvent is triggered when the body or comment of an issue or +// pull request includes a URL that matches a configured content reference +// domain. +// The Webhook event name is "content_reference". +// +// GitHub API docs: https://developer.github.com/webhooks/event-payloads/#content_reference +type ContentReferenceEvent struct { + Action *string `json:"action,omitempty"` + ContentReference *ContentReference `json:"content_reference,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// CreateEvent represents a created repository, branch, or tag. +// The Webhook event name is "create". +// +// Note: webhooks will not receive this event for created repositories. +// Additionally, webhooks will not receive this event for tags if more +// than three tags are pushed at once. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/github-event-types#createevent +type CreateEvent struct { + Ref *string `json:"ref,omitempty"` + // RefType is the object that was created. Possible values are: "repository", "branch", "tag". + RefType *string `json:"ref_type,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + Description *string `json:"description,omitempty"` + + // The following fields are only populated by Webhook events. + PusherType *string `json:"pusher_type,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeleteEvent represents a deleted branch or tag. +// The Webhook event name is "delete". +// +// Note: webhooks will not receive this event for tags if more than three tags +// are deleted at once. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/github-event-types#deleteevent +type DeleteEvent struct { + Ref *string `json:"ref,omitempty"` + // RefType is the object that was deleted. Possible values are: "branch", "tag". + RefType *string `json:"ref_type,omitempty"` + + // The following fields are only populated by Webhook events. + PusherType *string `json:"pusher_type,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeployKeyEvent is triggered when a deploy key is added or removed from a repository. +// The Webhook event name is "deploy_key". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#deploy_key +type DeployKeyEvent struct { + // Action is the action that was performed. Possible values are: + // "created" or "deleted". + Action *string `json:"action,omitempty"` + + // The deploy key resource. + Key *Key `json:"key,omitempty"` + + // The Repository where the event occurred + Repo *Repository `json:"repository,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeploymentEvent represents a deployment. +// The Webhook event name is "deployment". +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#deployment +type DeploymentEvent struct { + Deployment *Deployment `json:"deployment,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DeploymentStatusEvent represents a deployment status. +// The Webhook event name is "deployment_status". +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#deployment_status +type DeploymentStatusEvent struct { + Deployment *Deployment `json:"deployment,omitempty"` + DeploymentStatus *DeploymentStatus `json:"deployment_status,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// DiscussionEvent represents a webhook event for a discussion. +// The Webhook event name is "discussion". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#discussion +type DiscussionEvent struct { + // Action is the action that was performed. Possible values are: + // created, edited, deleted, pinned, unpinned, locked, unlocked, + // transferred, category_changed, answered, or unanswered. + Action *string `json:"action,omitempty"` + Discussion *Discussion `json:"discussion,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// Discussion represents a discussion in a GitHub DiscussionEvent. +type Discussion struct { + RepositoryURL *string `json:"repository_url,omitempty"` + DiscussionCategory *DiscussionCategory `json:"category,omitempty"` + AnswerHTMLURL *string `json:"answer_html_url,omitempty"` + AnswerChosenAt *Timestamp `json:"answer_chosen_at,omitempty"` + AnswerChosenBy *string `json:"answer_chosen_by,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + Title *string `json:"title,omitempty"` + User *User `json:"user,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Comments *int `json:"comments,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + ActiveLockReason *string `json:"active_lock_reason,omitempty"` + Body *string `json:"body,omitempty"` +} + +// DiscussionCategory represents a discussion category in a GitHub DiscussionEvent. +type DiscussionCategory struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Emoji *string `json:"emoji,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Slug *string `json:"slug,omitempty"` + IsAnswerable *bool `json:"is_answerable,omitempty"` +} + +// ForkEvent is triggered when a user forks a repository. +// The Webhook event name is "fork". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#fork +type ForkEvent struct { + // Forkee is the created repository. + Forkee *Repository `json:"forkee,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// GitHubAppAuthorizationEvent is triggered when a user's authorization for a +// GitHub Application is revoked. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#github_app_authorization +type GitHubAppAuthorizationEvent struct { + // The action performed. Possible value is: "revoked". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// Page represents a single Wiki page. +type Page struct { + PageName *string `json:"page_name,omitempty"` + Title *string `json:"title,omitempty"` + Summary *string `json:"summary,omitempty"` + Action *string `json:"action,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// GollumEvent is triggered when a Wiki page is created or updated. +// The Webhook event name is "gollum". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#gollum +type GollumEvent struct { + Pages []*Page `json:"pages,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// EditChange represents the changes when an issue, pull request, comment, +// or repository has been edited. +type EditChange struct { + Title *EditTitle `json:"title,omitempty"` + Body *EditBody `json:"body,omitempty"` + Base *EditBase `json:"base,omitempty"` + Repo *EditRepo `json:"repository,omitempty"` +} + +// EditTitle represents a pull-request title change. +type EditTitle struct { + From *string `json:"from,omitempty"` +} + +// EditBody represents a change of pull-request body. +type EditBody struct { + From *string `json:"from,omitempty"` +} + +// EditBase represents the change of a pull-request base branch. +type EditBase struct { + Ref *EditRef `json:"ref,omitempty"` + SHA *EditSHA `json:"sha,omitempty"` +} + +// EditRef represents a ref change of a pull-request. +type EditRef struct { + From *string `json:"from,omitempty"` +} + +// EditRepo represents a change of repository name. +type EditRepo struct { + Name *RepoName `json:"name,omitempty"` +} + +// RepoName represents a change of repository name. +type RepoName struct { + From *string `json:"from,omitempty"` +} + +// EditSHA represents a sha change of a pull-request. +type EditSHA struct { + From *string `json:"from,omitempty"` +} + +// ProjectChange represents the changes when a project has been edited. +type ProjectChange struct { + Name *ProjectName `json:"name,omitempty"` + Body *ProjectBody `json:"body,omitempty"` +} + +// ProjectName represents a project name change. +type ProjectName struct { + From *string `json:"from,omitempty"` +} + +// ProjectBody represents a project body change. +type ProjectBody struct { + From *string `json:"from,omitempty"` +} + +// ProjectCardChange represents the changes when a project card has been edited. +type ProjectCardChange struct { + Note *ProjectCardNote `json:"note,omitempty"` +} + +// ProjectCardNote represents a change of a note of a project card. +type ProjectCardNote struct { + From *string `json:"from,omitempty"` +} + +// ProjectColumnChange represents the changes when a project column has been edited. +type ProjectColumnChange struct { + Name *ProjectColumnName `json:"name,omitempty"` +} + +// ProjectColumnName represents a project column name change. +type ProjectColumnName struct { + From *string `json:"from,omitempty"` +} + +// TeamChange represents the changes when a team has been edited. +type TeamChange struct { + Description *TeamDescription `json:"description,omitempty"` + Name *TeamName `json:"name,omitempty"` + Privacy *TeamPrivacy `json:"privacy,omitempty"` + Repository *TeamRepository `json:"repository,omitempty"` +} + +// TeamDescription represents a team description change. +type TeamDescription struct { + From *string `json:"from,omitempty"` +} + +// TeamName represents a team name change. +type TeamName struct { + From *string `json:"from,omitempty"` +} + +// TeamPrivacy represents a team privacy change. +type TeamPrivacy struct { + From *string `json:"from,omitempty"` +} + +// TeamRepository represents a team repository permission change. +type TeamRepository struct { + Permissions *TeamPermissions `json:"permissions,omitempty"` +} + +// TeamPermissions represents a team permission change. +type TeamPermissions struct { + From *TeamPermissionsFrom `json:"from,omitempty"` +} + +// TeamPermissionsFrom represents a team permission change. +type TeamPermissionsFrom struct { + Admin *bool `json:"admin,omitempty"` + Pull *bool `json:"pull,omitempty"` + Push *bool `json:"push,omitempty"` +} + +// InstallationEvent is triggered when a GitHub App has been installed, uninstalled, suspend, unsuspended +// or new permissions have been accepted. +// The Webhook event name is "installation". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#installation +type InstallationEvent struct { + // The action that was performed. Can be either "created", "deleted", "suspend", "unsuspend" or "new_permissions_accepted". + Action *string `json:"action,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + // TODO key "requester" is not covered +} + +// InstallationRepositoriesEvent is triggered when a repository is added or +// removed from an installation. The Webhook event name is "installation_repositories". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#installation_repositories +type InstallationRepositoriesEvent struct { + // The action that was performed. Can be either "added" or "removed". + Action *string `json:"action,omitempty"` + RepositoriesAdded []*Repository `json:"repositories_added,omitempty"` + RepositoriesRemoved []*Repository `json:"repositories_removed,omitempty"` + RepositorySelection *string `json:"repository_selection,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// IssueCommentEvent is triggered when an issue comment is created on an issue +// or pull request. +// The Webhook event name is "issue_comment". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#issue_comment +type IssueCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". + Action *string `json:"action,omitempty"` + Issue *Issue `json:"issue,omitempty"` + Comment *IssueComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// IssuesEvent is triggered when an issue is opened, edited, deleted, transferred, +// pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled, +// locked, unlocked, milestoned, or demilestoned. +// The Webhook event name is "issues". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#issues +type IssuesEvent struct { + // Action is the action that was performed. Possible values are: "opened", + // "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened", + // "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked", + // "milestoned", or "demilestoned". + Action *string `json:"action,omitempty"` + Issue *Issue `json:"issue,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Label *Label `json:"label,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// LabelEvent is triggered when a repository's label is created, edited, or deleted. +// The Webhook event name is "label" +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#label +type LabelEvent struct { + // Action is the action that was performed. Possible values are: + // "created", "edited", "deleted" + Action *string `json:"action,omitempty"` + Label *Label `json:"label,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MarketplacePurchaseEvent is triggered when a user purchases, cancels, or changes +// their GitHub Marketplace plan. +// Webhook event name "marketplace_purchase". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#marketplace_purchase +type MarketplacePurchaseEvent struct { + // Action is the action that was performed. Possible values are: + // "purchased", "cancelled", "pending_change", "pending_change_cancelled", "changed". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + EffectiveDate *Timestamp `json:"effective_date,omitempty"` + MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"` + PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MemberEvent is triggered when a user is added as a collaborator to a repository. +// The Webhook event name is "member". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#member +type MemberEvent struct { + // Action is the action that was performed. Possible value is: "added". + Action *string `json:"action,omitempty"` + Member *User `json:"member,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MembershipEvent is triggered when a user is added or removed from a team. +// The Webhook event name is "membership". +// +// Events of this type are not visible in timelines, they are only used to +// trigger organization webhooks. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#membership +type MembershipEvent struct { + // Action is the action that was performed. Possible values are: "added", "removed". + Action *string `json:"action,omitempty"` + // Scope is the scope of the membership. Possible value is: "team". + Scope *string `json:"scope,omitempty"` + Member *User `json:"member,omitempty"` + Team *Team `json:"team,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// MetaEvent is triggered when the webhook that this event is configured on is deleted. +// This event will only listen for changes to the particular hook the event is installed on. +// Therefore, it must be selected for each hook that you'd like to receive meta events for. +// The Webhook event name is "meta". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#meta +type MetaEvent struct { + // Action is the action that was performed. Possible value is: "deleted". + Action *string `json:"action,omitempty"` + // The ID of the modified webhook. + HookID *int64 `json:"hook_id,omitempty"` + // The modified webhook. + // This will contain different keys based on the type of webhook it is: repository, + // organization, business, app, or GitHub Marketplace. + Hook *Hook `json:"hook,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted. +// The Webhook event name is "milestone". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#milestone +type MilestoneEvent struct { + // Action is the action that was performed. Possible values are: + // "created", "closed", "opened", "edited", "deleted" + Action *string `json:"action,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Org *Organization `json:"organization,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// OrganizationEvent is triggered when an organization is deleted and renamed, and when a user is added, +// removed, or invited to an organization. +// Events of this type are not visible in timelines. These events are only used to trigger organization hooks. +// Webhook event name is "organization". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#organization +type OrganizationEvent struct { + // Action is the action that was performed. + // Possible values are: "deleted", "renamed", "member_added", "member_removed", or "member_invited". + Action *string `json:"action,omitempty"` + + // Invitation is the invitation for the user or email if the action is "member_invited". + Invitation *Invitation `json:"invitation,omitempty"` + + // Membership is the membership between the user and the organization. + // Not present when the action is "member_invited". + Membership *Membership `json:"membership,omitempty"` + + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// OrgBlockEvent is triggered when an organization blocks or unblocks a user. +// The Webhook event name is "org_block". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#org_block +type OrgBlockEvent struct { + // Action is the action that was performed. + // Can be "blocked" or "unblocked". + Action *string `json:"action,omitempty"` + BlockedUser *User `json:"blocked_user,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// PackageEvent represents activity related to GitHub Packages. +// The Webhook event name is "package". +// +// This event is triggered when a GitHub Package is published or updated. +// +// GitHub API docs: https://developer.github.com/webhooks/event-payloads/#package +type PackageEvent struct { + // Action is the action that was performed. + // Can be "published" or "updated". + Action *string `json:"action,omitempty"` + Package *Package `json:"package,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// PageBuildEvent represents an attempted build of a GitHub Pages site, whether +// successful or not. +// The Webhook event name is "page_build". +// +// This event is triggered on push to a GitHub Pages enabled branch (gh-pages +// for project pages, master for user and organization pages). +// +// Events of this type are not visible in timelines, they are only used to trigger hooks. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#page_build +type PageBuildEvent struct { + Build *PagesBuild `json:"build,omitempty"` + + // The following fields are only populated by Webhook events. + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PingEvent is triggered when a Webhook is added to GitHub. +// +// GitHub API docs: https://developer.github.com/webhooks/#ping-event +type PingEvent struct { + // Random string of GitHub zen. + Zen *string `json:"zen,omitempty"` + // The ID of the webhook that triggered the ping. + HookID *int64 `json:"hook_id,omitempty"` + // The webhook configuration. + Hook *Hook `json:"hook,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ProjectEvent is triggered when project is created, modified or deleted. +// The webhook event name is "project". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#project +type ProjectEvent struct { + Action *string `json:"action,omitempty"` + Changes *ProjectChange `json:"changes,omitempty"` + Project *Project `json:"project,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ProjectCardEvent is triggered when a project card is created, updated, moved, converted to an issue, or deleted. +// The webhook event name is "project_card". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#project_card +type ProjectCardEvent struct { + Action *string `json:"action,omitempty"` + Changes *ProjectCardChange `json:"changes,omitempty"` + AfterID *int64 `json:"after_id,omitempty"` + ProjectCard *ProjectCard `json:"project_card,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// ProjectColumnEvent is triggered when a project column is created, updated, moved, or deleted. +// The webhook event name is "project_column". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#project_column +type ProjectColumnEvent struct { + Action *string `json:"action,omitempty"` + Changes *ProjectColumnChange `json:"changes,omitempty"` + AfterID *int64 `json:"after_id,omitempty"` + ProjectColumn *ProjectColumn `json:"project_column,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PublicEvent is triggered when a private repository is open sourced. +// According to GitHub: "Without a doubt: the best GitHub event." +// The Webhook event name is "public". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#public +type PublicEvent struct { + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PullRequestEvent is triggered when a pull request is assigned, unassigned, labeled, +// unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review, +// locked, unlocked, a pull request review is requested, or a review request is removed. +// The Webhook event name is "pull_request". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/github-event-types#pullrequestevent +type PullRequestEvent struct { + // Action is the action that was performed. Possible values are: + // "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled", + // "opened", "edited", "closed", "ready_for_review", "locked", "unlocked", or "reopened". + // If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits. + // If the action is "closed" and the "merged" key is "true", the pull request was merged. + // While webhooks are also triggered when a pull request is synchronized, Events API timelines + // don't include pull request events with the "synchronize" action. + Action *string `json:"action,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Number *int `json:"number,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. + // A request affecting multiple reviewers at once is split into multiple + // such event deliveries, each with a single, different RequestedReviewer. + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + // In the event that a team is requested instead of a user, "requested_team" gets sent in place of + // "requested_user" with the same delivery behavior. + RequestedTeam *Team `json:"requested_team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated when the Action is "synchronize". + Before *string `json:"before,omitempty"` + After *string `json:"after,omitempty"` +} + +// PullRequestReviewEvent is triggered when a review is submitted on a pull +// request. +// The Webhook event name is "pull_request_review". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review +type PullRequestReviewEvent struct { + // Action is always "submitted". + Action *string `json:"action,omitempty"` + Review *PullRequestReview `json:"review,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +// PullRequestReviewCommentEvent is triggered when a comment is created on a +// portion of the unified diff of a pull request. +// The Webhook event name is "pull_request_review_comment". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review_comment +type PullRequestReviewCommentEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "created", "edited", "deleted". + Action *string `json:"action,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + Comment *PullRequestComment `json:"comment,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PullRequestReviewThreadEvent is triggered when a comment made as part of a +// review of a pull request is marked resolved or unresolved. +// The Webhook event name is "pull_request_review_thread". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#pull_request_review_thread +type PullRequestReviewThreadEvent struct { + // Action is the action that was performed on the comment. + // Possible values are: "resolved", "unresolved". + Action *string `json:"action,omitempty"` + Thread *PullRequestThread `json:"thread,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// PullRequestTargetEvent is triggered when a pull request is assigned, unassigned, labeled, +// unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review, +// locked, unlocked, a pull request review is requested, or a review request is removed. +// The Webhook event name is "pull_request_target". +// +// GitHub API docs: https://docs.github.com/en/actions/events-that-trigger-workflows#pull_request_target +type PullRequestTargetEvent struct { + // Action is the action that was performed. Possible values are: + // "assigned", "unassigned", "labeled", "unlabeled", "opened", "edited", "closed", "reopened", + // "ready_for_review", "locked", "unlocked", "review_requested" or "review_request_removed". + // If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits. + // If the action is "closed" and the "merged" key is "true", the pull request was merged. + // While webhooks are also triggered when a pull request is synchronized, Events API timelines + // don't include pull request events with the "synchronize" action. + Action *string `json:"action,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Number *int `json:"number,omitempty"` + PullRequest *PullRequest `json:"pull_request,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + // RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries. + // A request affecting multiple reviewers at once is split into multiple + // such event deliveries, each with a single, different RequestedReviewer. + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + // In the event that a team is requested instead of a user, "requested_team" gets sent in place of + // "requested_user" with the same delivery behavior. + RequestedTeam *Team `json:"requested_team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries. + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` + + // The following fields are only populated when the Action is "synchronize". + Before *string `json:"before,omitempty"` + After *string `json:"after,omitempty"` +} + +// PushEvent represents a git push to a GitHub repository. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#push +type PushEvent struct { + PushID *int64 `json:"push_id,omitempty"` + Head *string `json:"head,omitempty"` + Ref *string `json:"ref,omitempty"` + Size *int `json:"size,omitempty"` + Commits []*HeadCommit `json:"commits,omitempty"` + Before *string `json:"before,omitempty"` + DistinctSize *int `json:"distinct_size,omitempty"` + + // The following fields are only populated by Webhook events. + Action *string `json:"action,omitempty"` + After *string `json:"after,omitempty"` + Created *bool `json:"created,omitempty"` + Deleted *bool `json:"deleted,omitempty"` + Forced *bool `json:"forced,omitempty"` + BaseRef *string `json:"base_ref,omitempty"` + Compare *string `json:"compare,omitempty"` + Repo *PushEventRepository `json:"repository,omitempty"` + HeadCommit *HeadCommit `json:"head_commit,omitempty"` + Pusher *User `json:"pusher,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` + + // The following field is only present when the webhook is triggered on + // a repository belonging to an organization. + Organization *Organization `json:"organization,omitempty"` +} + +func (p PushEvent) String() string { + return Stringify(p) +} + +// HeadCommit represents a git commit in a GitHub PushEvent. +type HeadCommit struct { + Message *string `json:"message,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + URL *string `json:"url,omitempty"` + Distinct *bool `json:"distinct,omitempty"` + + // The following fields are only populated by Events API. + SHA *string `json:"sha,omitempty"` + + // The following fields are only populated by Webhook events. + ID *string `json:"id,omitempty"` + TreeID *string `json:"tree_id,omitempty"` + Timestamp *Timestamp `json:"timestamp,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Added []string `json:"added,omitempty"` + Removed []string `json:"removed,omitempty"` + Modified []string `json:"modified,omitempty"` +} + +func (h HeadCommit) String() string { + return Stringify(h) +} + +// PushEventRepository represents the repo object in a PushEvent payload. +type PushEventRepository struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + FullName *string `json:"full_name,omitempty"` + Owner *User `json:"owner,omitempty"` + Private *bool `json:"private,omitempty"` + Description *string `json:"description,omitempty"` + Fork *bool `json:"fork,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PushedAt *Timestamp `json:"pushed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Homepage *string `json:"homepage,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + Size *int `json:"size,omitempty"` + StargazersCount *int `json:"stargazers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` + Language *string `json:"language,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasDownloads *bool `json:"has_downloads,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasPages *bool `json:"has_pages,omitempty"` + ForksCount *int `json:"forks_count,omitempty"` + Archived *bool `json:"archived,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + OpenIssuesCount *int `json:"open_issues_count,omitempty"` + DefaultBranch *string `json:"default_branch,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + Organization *string `json:"organization,omitempty"` + URL *string `json:"url,omitempty"` + ArchiveURL *string `json:"archive_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + SSHURL *string `json:"ssh_url,omitempty"` + CloneURL *string `json:"clone_url,omitempty"` + SVNURL *string `json:"svn_url,omitempty"` +} + +// PushEventRepoOwner is a basic representation of user/org in a PushEvent payload. +type PushEventRepoOwner struct { + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` +} + +// ReleaseEvent is triggered when a release is published, unpublished, created, +// edited, deleted, or prereleased. +// The Webhook event name is "release". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#release +type ReleaseEvent struct { + // Action is the action that was performed. Possible values are: "published", "unpublished", + // "created", "edited", "deleted", or "prereleased". + Action *string `json:"action,omitempty"` + Release *RepositoryRelease `json:"release,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// RepositoryEvent is triggered when a repository is created, archived, unarchived, +// renamed, edited, transferred, made public, or made private. Organization hooks are +// also trigerred when a repository is deleted. +// The Webhook event name is "repository". +// +// Events of this type are not visible in timelines, they are only used to +// trigger organization webhooks. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#repository +type RepositoryEvent struct { + // Action is the action that was performed. Possible values are: "created", + // "deleted" (organization hooks only), "archived", "unarchived", "edited", "renamed", + // "transferred", "publicized", or "privatized". + Action *string `json:"action,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Changes *EditChange `json:"changes,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// RepositoryDispatchEvent is triggered when a client sends a POST request to the repository dispatch event endpoint. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#repository_dispatch +type RepositoryDispatchEvent struct { + // Action is the event_type that submitted with the repository dispatch payload. Value can be any string. + Action *string `json:"action,omitempty"` + Branch *string `json:"branch,omitempty"` + ClientPayload json.RawMessage `json:"client_payload,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// RepositoryImportEvent represents the activity related to a repository being imported to GitHub. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#repository_import +type RepositoryImportEvent struct { + // Status represents the final state of the import. This can be one of "success", "cancelled", or "failure". + Status *string `json:"status,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} + +// RepositoryVulnerabilityAlertEvent is triggered when a security alert is created, dismissed, or resolved. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#repository_vulnerability_alert +type RepositoryVulnerabilityAlertEvent struct { + // Action is the action that was performed. Possible values are: "create", "dismiss", "resolve". + Action *string `json:"action,omitempty"` + + // The security alert of the vulnerable dependency. + Alert *RepositoryVulnerabilityAlert `json:"alert,omitempty"` + + // The repository of the vulnerable dependency. + Repository *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` + + // The user that triggered the event. + Sender *User `json:"sender,omitempty"` +} + +// RepositoryVulnerabilityAlert represents a repository security alert. +type RepositoryVulnerabilityAlert struct { + ID *int64 `json:"id,omitempty"` + AffectedRange *string `json:"affected_range,omitempty"` + AffectedPackageName *string `json:"affected_package_name,omitempty"` + ExternalReference *string `json:"external_reference,omitempty"` + ExternalIdentifier *string `json:"external_identifier,omitempty"` + GitHubSecurityAdvisoryID *string `json:"ghsa_id,omitempty"` + Severity *string `json:"severity,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + FixedIn *string `json:"fixed_in,omitempty"` + Dismisser *User `json:"dismisser,omitempty"` + DismissReason *string `json:"dismiss_reason,omitempty"` + DismissedAt *Timestamp `json:"dismissed_at,omitempty"` +} + +// SecretScanningAlertEvent is triggered when a secret scanning alert occurs in a repository. +// The Webhook name is secret_scanning_alert. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#secret_scanning_alert +type SecretScanningAlertEvent struct { + // Action is the action that was performed. Possible values are: "created", "resolved", or "reopened". + Action *string `json:"action,omitempty"` + + // Alert is the secret scanning alert involved in the event. + Alert *SecretScanningAlert `json:"alert,omitempty"` + + // Only populated by the "resolved" and "reopen" actions + Sender *User `json:"sender,omitempty"` + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// StarEvent is triggered when a star is added or removed from a repository. +// The Webhook event name is "star". +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#star +type StarEvent struct { + // Action is the action that was performed. Possible values are: "created" or "deleted". + Action *string `json:"action,omitempty"` + + // StarredAt is the time the star was created. It will be null for the "deleted" action. + StarredAt *Timestamp `json:"starred_at,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// StatusEvent is triggered when the status of a Git commit changes. +// The Webhook event name is "status". +// +// Events of this type are not visible in timelines, they are only used to +// trigger hooks. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#status +type StatusEvent struct { + SHA *string `json:"sha,omitempty"` + // State is the new state. Possible values are: "pending", "success", "failure", "error". + State *string `json:"state,omitempty"` + Description *string `json:"description,omitempty"` + TargetURL *string `json:"target_url,omitempty"` + Branches []*Branch `json:"branches,omitempty"` + + // The following fields are only populated by Webhook events. + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Context *string `json:"context,omitempty"` + Commit *RepositoryCommit `json:"commit,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// TeamEvent is triggered when an organization's team is created, modified or deleted. +// The Webhook event name is "team". +// +// Events of this type are not visible in timelines. These events are only used +// to trigger hooks. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#team +type TeamEvent struct { + Action *string `json:"action,omitempty"` + Team *Team `json:"team,omitempty"` + Changes *TeamChange `json:"changes,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// TeamAddEvent is triggered when a repository is added to a team. +// The Webhook event name is "team_add". +// +// Events of this type are not visible in timelines. These events are only used +// to trigger hooks. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#team_add +type TeamAddEvent struct { + Team *Team `json:"team,omitempty"` + Repo *Repository `json:"repository,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// UserEvent is triggered when a user is created or deleted. +// The Webhook event name is "user". +// +// Only global webhooks can subscribe to this event type. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/activity/events/types/#userevent-enterprise +type UserEvent struct { + User *User `json:"user,omitempty"` + // The action performed. Possible values are: "created" or "deleted". + Action *string `json:"action,omitempty"` + Enterprise *Enterprise `json:"enterprise,omitempty"` + Sender *User `json:"sender,omitempty"` + + // The following fields are only populated by Webhook events. + Installation *Installation `json:"installation,omitempty"` +} + +// WatchEvent is related to starring a repository, not watching. See this API +// blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/ +// +// The event’s actor is the user who starred a repository, and the event’s +// repository is the repository that was starred. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#watch +type WatchEvent struct { + // Action is the action that was performed. Possible value is: "started". + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// WorkflowDispatchEvent is triggered when someone triggers a workflow run on GitHub or +// sends a POST request to the create a workflow dispatch event endpoint. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#workflow_dispatch +type WorkflowDispatchEvent struct { + Inputs json.RawMessage `json:"inputs,omitempty"` + Ref *string `json:"ref,omitempty"` + Workflow *string `json:"workflow,omitempty"` + + // The following fields are only populated by Webhook events. + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// WorkflowJobEvent is triggered when a job is queued, started or completed. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_job +type WorkflowJobEvent struct { + WorkflowJob *WorkflowJob `json:"workflow_job,omitempty"` + + Action *string `json:"action,omitempty"` + + // The following fields are only populated by Webhook events. + + // Org is not nil when the webhook is configured for an organization or the event + // occurs from activity in a repository owned by an organization. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// WorkflowRunEvent is triggered when a GitHub Actions workflow run is requested or completed. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhook-events-and-payloads#workflow_run +type WorkflowRunEvent struct { + Action *string `json:"action,omitempty"` + Workflow *Workflow `json:"workflow,omitempty"` + WorkflowRun *WorkflowRun `json:"workflow_run,omitempty"` + + // The following fields are only populated by Webhook events. + Org *Organization `json:"organization,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Sender *User `json:"sender,omitempty"` + Installation *Installation `json:"installation,omitempty"` +} + +// SecurityAdvisory represents the advisory object in SecurityAdvisoryEvent payload. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#security_advisory +type SecurityAdvisory struct { + GHSAID *string `json:"ghsa_id,omitempty"` + Summary *string `json:"summary,omitempty"` + Description *string `json:"description,omitempty"` + Severity *string `json:"severity,omitempty"` + Identifiers []*AdvisoryIdentifier `json:"identifiers,omitempty"` + References []*AdvisoryReference `json:"references,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + WithdrawnAt *Timestamp `json:"withdrawn_at,omitempty"` + Vulnerabilities []*AdvisoryVulnerability `json:"vulnerabilities,omitempty"` +} + +// AdvisoryIdentifier represents the identifier for a Security Advisory. +type AdvisoryIdentifier struct { + Value *string `json:"value,omitempty"` + Type *string `json:"type,omitempty"` +} + +// AdvisoryReference represents the reference url for the security advisory. +type AdvisoryReference struct { + URL *string `json:"url,omitempty"` +} + +// AdvisoryVulnerability represents the vulnerability object for a Security Advisory. +type AdvisoryVulnerability struct { + Package *VulnerabilityPackage `json:"package,omitempty"` + Severity *string `json:"severity,omitempty"` + VulnerableVersionRange *string `json:"vulnerable_version_range,omitempty"` + FirstPatchedVersion *FirstPatchedVersion `json:"first_patched_version,omitempty"` +} + +// VulnerabilityPackage represents the package object for an Advisory Vulnerability. +type VulnerabilityPackage struct { + Ecosystem *string `json:"ecosystem,omitempty"` + Name *string `json:"name,omitempty"` +} + +// FirstPatchedVersion represents the identifier for the first patched version of that vulnerability. +type FirstPatchedVersion struct { + Identifier *string `json:"identifier,omitempty"` +} + +// SecurityAdvisoryEvent is triggered when a security-related vulnerability is found in software on GitHub. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#security_advisory +type SecurityAdvisoryEvent struct { + Action *string `json:"action,omitempty"` + SecurityAdvisory *SecurityAdvisory `json:"security_advisory,omitempty"` +} + +// CodeScanningAlertEvent is triggered when a code scanning finds a potential vulnerability or error in your code. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#code_scanning_alert +type CodeScanningAlertEvent struct { + Action *string `json:"action,omitempty"` + Alert *Alert `json:"alert,omitempty"` + Ref *string `json:"ref,omitempty"` + // CommitOID is the commit SHA of the code scanning alert + CommitOID *string `json:"commit_oid,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Org *Organization `json:"organization,omitempty"` + Sender *User `json:"sender,omitempty"` +} diff --git a/vendor/github.com/google/go-github/v45/github/gists.go b/vendor/github.com/google/go-github/v45/github/gists.go new file mode 100644 index 0000000000..ecdc6f2726 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/gists.go @@ -0,0 +1,368 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// GistsService handles communication with the Gist related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/gists +type GistsService service + +// Gist represents a GitHub's gist. +type Gist struct { + ID *string `json:"id,omitempty"` + Description *string `json:"description,omitempty"` + Public *bool `json:"public,omitempty"` + Owner *User `json:"owner,omitempty"` + Files map[GistFilename]GistFile `json:"files,omitempty"` + Comments *int `json:"comments,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GitPullURL *string `json:"git_pull_url,omitempty"` + GitPushURL *string `json:"git_push_url,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (g Gist) String() string { + return Stringify(g) +} + +// GistFilename represents filename on a gist. +type GistFilename string + +// GistFile represents a file on a gist. +type GistFile struct { + Size *int `json:"size,omitempty"` + Filename *string `json:"filename,omitempty"` + Language *string `json:"language,omitempty"` + Type *string `json:"type,omitempty"` + RawURL *string `json:"raw_url,omitempty"` + Content *string `json:"content,omitempty"` +} + +func (g GistFile) String() string { + return Stringify(g) +} + +// GistCommit represents a commit on a gist. +type GistCommit struct { + URL *string `json:"url,omitempty"` + Version *string `json:"version,omitempty"` + User *User `json:"user,omitempty"` + ChangeStatus *CommitStats `json:"change_status,omitempty"` + CommittedAt *Timestamp `json:"committed_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (gc GistCommit) String() string { + return Stringify(gc) +} + +// GistFork represents a fork of a gist. +type GistFork struct { + URL *string `json:"url,omitempty"` + User *User `json:"user,omitempty"` + ID *string `json:"id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (gf GistFork) String() string { + return Stringify(gf) +} + +// GistListOptions specifies the optional parameters to the +// GistsService.List, GistsService.ListAll, and GistsService.ListStarred methods. +type GistListOptions struct { + // Since filters Gists by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// List gists for a user. Passing the empty string will list +// all public gists if called anonymously. However, if the call +// is authenticated, it will returns all gists for the authenticated +// user. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#list-gists-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#list-gists-for-a-user +func (s *GistsService) List(ctx context.Context, user string, opts *GistListOptions) ([]*Gist, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/gists", user) + } else { + u = "gists" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// ListAll lists all public gists. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#list-public-gists +func (s *GistsService) ListAll(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) { + u, err := addOptions("gists/public", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// ListStarred lists starred gists of authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#list-starred-gists +func (s *GistsService) ListStarred(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) { + u, err := addOptions("gists/starred", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gists []*Gist + resp, err := s.client.Do(ctx, req, &gists) + if err != nil { + return nil, resp, err + } + + return gists, resp, nil +} + +// Get a single gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#get-a-gist +func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + gist := new(Gist) + resp, err := s.client.Do(ctx, req, gist) + if err != nil { + return nil, resp, err + } + + return gist, resp, nil +} + +// GetRevision gets a specific revision of a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#get-a-gist-revision +func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v/%v", id, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + gist := new(Gist) + resp, err := s.client.Do(ctx, req, gist) + if err != nil { + return nil, resp, err + } + + return gist, resp, nil +} + +// Create a gist for authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#create-a-gist +func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response, error) { + u := "gists" + req, err := s.client.NewRequest("POST", u, gist) + if err != nil { + return nil, nil, err + } + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// Edit a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#update-a-gist +func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("PATCH", u, gist) + if err != nil { + return nil, nil, err + } + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// ListCommits lists commits of a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#list-gist-commits +func (s *GistsService) ListCommits(ctx context.Context, id string, opts *ListOptions) ([]*GistCommit, *Response, error) { + u := fmt.Sprintf("gists/%v/commits", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gistCommits []*GistCommit + resp, err := s.client.Do(ctx, req, &gistCommits) + if err != nil { + return nil, resp, err + } + + return gistCommits, resp, nil +} + +// Delete a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#delete-a-gist +func (s *GistsService) Delete(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Star a gist on behalf of authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#star-a-gist +func (s *GistsService) Star(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unstar a gist on a behalf of authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#unstar-a-gist +func (s *GistsService) Unstar(ctx context.Context, id string) (*Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// IsStarred checks if a gist is starred by authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#check-if-a-gist-is-starred +func (s *GistsService) IsStarred(ctx context.Context, id string) (bool, *Response, error) { + u := fmt.Sprintf("gists/%v/star", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + starred, err := parseBoolResponse(err) + return starred, resp, err +} + +// Fork a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#fork-a-gist +func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, error) { + u := fmt.Sprintf("gists/%v/forks", id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + g := new(Gist) + resp, err := s.client.Do(ctx, req, g) + if err != nil { + return nil, resp, err + } + + return g, resp, nil +} + +// ListForks lists forks of a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/gists#list-gist-forks +func (s *GistsService) ListForks(ctx context.Context, id string, opts *ListOptions) ([]*GistFork, *Response, error) { + u := fmt.Sprintf("gists/%v/forks", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var gistForks []*GistFork + resp, err := s.client.Do(ctx, req, &gistForks) + if err != nil { + return nil, resp, err + } + + return gistForks, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/gists_comments.go b/vendor/github.com/google/go-github/v45/github/gists_comments.go new file mode 100644 index 0000000000..d551e9a11d --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/gists_comments.go @@ -0,0 +1,119 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// GistComment represents a Gist comment. +type GistComment struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Body *string `json:"body,omitempty"` + User *User `json:"user,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` +} + +func (g GistComment) String() string { + return Stringify(g) +} + +// ListComments lists all comments for a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/comments#list-gist-comments +func (s *GistsService) ListComments(ctx context.Context, gistID string, opts *ListOptions) ([]*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments", gistID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*GistComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment retrieves a single comment from a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/comments#get-a-gist-comment +func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// CreateComment creates a comment for a gist. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/comments#create-a-gist-comment +func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments", gistID) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment edits an existing gist comment. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/comments#update-a-gist-comment +func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(GistComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a gist comment. +// +// GitHub API docs: https://docs.github.com/en/rest/gists/comments#delete-a-gist-comment +func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) { + u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/git.go b/vendor/github.com/google/go-github/v45/github/git.go new file mode 100644 index 0000000000..8960de7b14 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/git.go @@ -0,0 +1,12 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// GitService handles communication with the git data related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/git/ +type GitService service diff --git a/vendor/github.com/google/go-github/v45/github/git_blobs.go b/vendor/github.com/google/go-github/v45/github/git_blobs.go new file mode 100644 index 0000000000..da0485ccbe --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/git_blobs.go @@ -0,0 +1,82 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" +) + +// Blob represents a blob object. +type Blob struct { + Content *string `json:"content,omitempty"` + Encoding *string `json:"encoding,omitempty"` + SHA *string `json:"sha,omitempty"` + Size *int `json:"size,omitempty"` + URL *string `json:"url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// GetBlob fetches a blob from a repo given a SHA. +// +// GitHub API docs: https://docs.github.com/en/rest/git/blobs#get-a-blob +func (s *GitService) GetBlob(ctx context.Context, owner string, repo string, sha string) (*Blob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + blob := new(Blob) + resp, err := s.client.Do(ctx, req, blob) + if err != nil { + return nil, resp, err + } + + return blob, resp, nil +} + +// GetBlobRaw fetches a blob's contents from a repo. +// Unlike GetBlob, it returns the raw bytes rather than the base64-encoded data. +// +// GitHub API docs: https://docs.github.com/en/rest/git/blobs#get-a-blob +func (s *GitService) GetBlobRaw(ctx context.Context, owner, repo, sha string) ([]byte, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", "application/vnd.github.v3.raw") + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return nil, resp, err + } + + return buf.Bytes(), resp, nil +} + +// CreateBlob creates a blob object. +// +// GitHub API docs: https://docs.github.com/en/rest/git/blobs#create-a-blob +func (s *GitService) CreateBlob(ctx context.Context, owner string, repo string, blob *Blob) (*Blob, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/blobs", owner, repo) + req, err := s.client.NewRequest("POST", u, blob) + if err != nil { + return nil, nil, err + } + + t := new(Blob) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/git_commits.go b/vendor/github.com/google/go-github/v45/github/git_commits.go new file mode 100644 index 0000000000..baedb3d686 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/git_commits.go @@ -0,0 +1,200 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "errors" + "fmt" + "strings" + "time" + + "golang.org/x/crypto/openpgp" +) + +// SignatureVerification represents GPG signature verification. +type SignatureVerification struct { + Verified *bool `json:"verified,omitempty"` + Reason *string `json:"reason,omitempty"` + Signature *string `json:"signature,omitempty"` + Payload *string `json:"payload,omitempty"` +} + +// Commit represents a GitHub commit. +type Commit struct { + SHA *string `json:"sha,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Message *string `json:"message,omitempty"` + Tree *Tree `json:"tree,omitempty"` + Parents []*Commit `json:"parents,omitempty"` + Stats *CommitStats `json:"stats,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + Verification *SignatureVerification `json:"verification,omitempty"` + NodeID *string `json:"node_id,omitempty"` + + // CommentCount is the number of GitHub comments on the commit. This + // is only populated for requests that fetch GitHub data like + // Pulls.ListCommits, Repositories.ListCommits, etc. + CommentCount *int `json:"comment_count,omitempty"` + + // SigningKey denotes a key to sign the commit with. If not nil this key will + // be used to sign the commit. The private key must be present and already + // decrypted. Ignored if Verification.Signature is defined. + SigningKey *openpgp.Entity `json:"-"` +} + +func (c Commit) String() string { + return Stringify(c) +} + +// CommitAuthor represents the author or committer of a commit. The commit +// author may not correspond to a GitHub User. +type CommitAuthor struct { + Date *time.Time `json:"date,omitempty"` + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` + + // The following fields are only populated by Webhook events. + Login *string `json:"username,omitempty"` // Renamed for go-github consistency. +} + +func (c CommitAuthor) String() string { + return Stringify(c) +} + +// GetCommit fetches the Commit object for a given SHA. +// +// GitHub API docs: https://docs.github.com/en/rest/git/commits#get-a-commit +func (s *GitService) GetCommit(ctx context.Context, owner string, repo string, sha string) (*Commit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + c := new(Commit) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// createCommit represents the body of a CreateCommit request. +type createCommit struct { + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` + Message *string `json:"message,omitempty"` + Tree *string `json:"tree,omitempty"` + Parents []string `json:"parents,omitempty"` + Signature *string `json:"signature,omitempty"` +} + +// CreateCommit creates a new commit in a repository. +// commit must not be nil. +// +// The commit.Committer is optional and will be filled with the commit.Author +// data if omitted. If the commit.Author is omitted, it will be filled in with +// the authenticated user’s information and the current date. +// +// GitHub API docs: https://docs.github.com/en/rest/git/commits#create-a-commit +func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string, commit *Commit) (*Commit, *Response, error) { + if commit == nil { + return nil, nil, fmt.Errorf("commit must be provided") + } + + u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo) + + parents := make([]string, len(commit.Parents)) + for i, parent := range commit.Parents { + parents[i] = *parent.SHA + } + + body := &createCommit{ + Author: commit.Author, + Committer: commit.Committer, + Message: commit.Message, + Parents: parents, + } + if commit.Tree != nil { + body.Tree = commit.Tree.SHA + } + if commit.SigningKey != nil { + signature, err := createSignature(commit.SigningKey, body) + if err != nil { + return nil, nil, err + } + body.Signature = &signature + } + if commit.Verification != nil { + body.Signature = commit.Verification.Signature + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + c := new(Commit) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +func createSignature(signingKey *openpgp.Entity, commit *createCommit) (string, error) { + if signingKey == nil || commit == nil { + return "", errors.New("createSignature: invalid parameters") + } + + message, err := createSignatureMessage(commit) + if err != nil { + return "", err + } + + writer := new(bytes.Buffer) + reader := bytes.NewReader([]byte(message)) + if err := openpgp.ArmoredDetachSign(writer, signingKey, reader, nil); err != nil { + return "", err + } + + return writer.String(), nil +} + +func createSignatureMessage(commit *createCommit) (string, error) { + if commit == nil || commit.Message == nil || *commit.Message == "" || commit.Author == nil { + return "", errors.New("createSignatureMessage: invalid parameters") + } + + var message []string + + if commit.Tree != nil { + message = append(message, fmt.Sprintf("tree %s", *commit.Tree)) + } + + for _, parent := range commit.Parents { + message = append(message, fmt.Sprintf("parent %s", parent)) + } + + message = append(message, fmt.Sprintf("author %s <%s> %d %s", commit.Author.GetName(), commit.Author.GetEmail(), commit.Author.GetDate().Unix(), commit.Author.GetDate().Format("-0700"))) + + committer := commit.Committer + if committer == nil { + committer = commit.Author + } + + // There needs to be a double newline after committer + message = append(message, fmt.Sprintf("committer %s <%s> %d %s\n", committer.GetName(), committer.GetEmail(), committer.GetDate().Unix(), committer.GetDate().Format("-0700"))) + message = append(message, *commit.Message) + + return strings.Join(message, "\n"), nil +} diff --git a/vendor/github.com/google/go-github/v45/github/git_refs.go b/vendor/github.com/google/go-github/v45/github/git_refs.go new file mode 100644 index 0000000000..883975cc0f --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/git_refs.go @@ -0,0 +1,175 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/url" + "strings" +) + +// Reference represents a GitHub reference. +type Reference struct { + Ref *string `json:"ref"` + URL *string `json:"url"` + Object *GitObject `json:"object"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r Reference) String() string { + return Stringify(r) +} + +// GitObject represents a Git object. +type GitObject struct { + Type *string `json:"type"` + SHA *string `json:"sha"` + URL *string `json:"url"` +} + +func (o GitObject) String() string { + return Stringify(o) +} + +// createRefRequest represents the payload for creating a reference. +type createRefRequest struct { + Ref *string `json:"ref"` + SHA *string `json:"sha"` +} + +// updateRefRequest represents the payload for updating a reference. +type updateRefRequest struct { + SHA *string `json:"sha"` + Force *bool `json:"force"` +} + +// GetRef fetches a single reference in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/git/refs#get-a-reference +func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/ref/%v", owner, repo, refURLEscape(ref)) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// refURLEscape escapes every path segment of the given ref. Those must +// not contain escaped "/" - as "%2F" - or github will not recognize it. +func refURLEscape(ref string) string { + parts := strings.Split(ref, "/") + for i, s := range parts { + parts[i] = url.PathEscape(s) + } + return strings.Join(parts, "/") +} + +// ReferenceListOptions specifies optional parameters to the +// GitService.ListMatchingRefs method. +type ReferenceListOptions struct { + Ref string `url:"-"` + + ListOptions +} + +// ListMatchingRefs lists references in a repository that match a supplied ref. +// Use an empty ref to list all references. +// +// GitHub API docs: https://docs.github.com/en/rest/git/refs#list-matching-references +func (s *GitService) ListMatchingRefs(ctx context.Context, owner, repo string, opts *ReferenceListOptions) ([]*Reference, *Response, error) { + var ref string + if opts != nil { + ref = strings.TrimPrefix(opts.Ref, "refs/") + } + u := fmt.Sprintf("repos/%v/%v/git/matching-refs/%v", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var rs []*Reference + resp, err := s.client.Do(ctx, req, &rs) + if err != nil { + return nil, resp, err + } + + return rs, resp, nil +} + +// CreateRef creates a new ref in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/git/refs#create-a-reference +func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo) + req, err := s.client.NewRequest("POST", u, &createRefRequest{ + // back-compat with previous behavior that didn't require 'refs/' prefix + Ref: String("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")), + SHA: ref.Object.SHA, + }) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdateRef updates an existing ref in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/git/refs#update-a-reference +func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) { + refPath := strings.TrimPrefix(*ref.Ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refPath) + req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{ + SHA: ref.Object.SHA, + Force: &force, + }) + if err != nil { + return nil, nil, err + } + + r := new(Reference) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DeleteRef deletes a ref from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/git/refs#delete-a-reference +func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) { + ref = strings.TrimPrefix(ref, "refs/") + u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refURLEscape(ref)) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/git_tags.go b/vendor/github.com/google/go-github/v45/github/git_tags.go new file mode 100644 index 0000000000..30d7b2c2d2 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/git_tags.go @@ -0,0 +1,84 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Tag represents a tag object. +type Tag struct { + Tag *string `json:"tag,omitempty"` + SHA *string `json:"sha,omitempty"` + URL *string `json:"url,omitempty"` + Message *string `json:"message,omitempty"` + Tagger *CommitAuthor `json:"tagger,omitempty"` + Object *GitObject `json:"object,omitempty"` + Verification *SignatureVerification `json:"verification,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// createTagRequest represents the body of a CreateTag request. This is mostly +// identical to Tag with the exception that the object SHA and Type are +// top-level fields, rather than being nested inside a JSON object. +type createTagRequest struct { + Tag *string `json:"tag,omitempty"` + Message *string `json:"message,omitempty"` + Object *string `json:"object,omitempty"` + Type *string `json:"type,omitempty"` + Tagger *CommitAuthor `json:"tagger,omitempty"` +} + +// GetTag fetches a tag from a repo given a SHA. +// +// GitHub API docs: https://docs.github.com/en/rest/git/tags#get-a-tag +func (s *GitService) GetTag(ctx context.Context, owner string, repo string, sha string) (*Tag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/tags/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + tag := new(Tag) + resp, err := s.client.Do(ctx, req, tag) + if err != nil { + return nil, resp, err + } + + return tag, resp, nil +} + +// CreateTag creates a tag object. +// +// GitHub API docs: https://docs.github.com/en/rest/git/tags#create-a-tag-object +func (s *GitService) CreateTag(ctx context.Context, owner string, repo string, tag *Tag) (*Tag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/tags", owner, repo) + + // convert Tag into a createTagRequest + tagRequest := &createTagRequest{ + Tag: tag.Tag, + Message: tag.Message, + Tagger: tag.Tagger, + } + if tag.Object != nil { + tagRequest.Object = tag.Object.SHA + tagRequest.Type = tag.Object.Type + } + + req, err := s.client.NewRequest("POST", u, tagRequest) + if err != nil { + return nil, nil, err + } + + t := new(Tag) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/git_trees.go b/vendor/github.com/google/go-github/v45/github/git_trees.go new file mode 100644 index 0000000000..db28976e03 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/git_trees.go @@ -0,0 +1,162 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// Tree represents a GitHub tree. +type Tree struct { + SHA *string `json:"sha,omitempty"` + Entries []*TreeEntry `json:"tree,omitempty"` + + // Truncated is true if the number of items in the tree + // exceeded GitHub's maximum limit and the Entries were truncated + // in the response. Only populated for requests that fetch + // trees like Git.GetTree. + Truncated *bool `json:"truncated,omitempty"` +} + +func (t Tree) String() string { + return Stringify(t) +} + +// TreeEntry represents the contents of a tree structure. TreeEntry can +// represent either a blob, a commit (in the case of a submodule), or another +// tree. +type TreeEntry struct { + SHA *string `json:"sha,omitempty"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (t TreeEntry) String() string { + return Stringify(t) +} + +// treeEntryWithFileDelete is used internally to delete a file whose +// Content and SHA fields are empty. It does this by removing the "omitempty" +// tag modifier on the SHA field which causes the GitHub API to receive +// {"sha":null} and thereby delete the file. +type treeEntryWithFileDelete struct { + SHA *string `json:"sha"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (t *TreeEntry) MarshalJSON() ([]byte, error) { + if t.SHA == nil && t.Content == nil { + return json.Marshal(struct { + SHA *string `json:"sha"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + }{ + nil, + t.Path, + t.Mode, + t.Type, + }) + } + return json.Marshal(struct { + SHA *string `json:"sha,omitempty"` + Path *string `json:"path,omitempty"` + Mode *string `json:"mode,omitempty"` + Type *string `json:"type,omitempty"` + Size *int `json:"size,omitempty"` + Content *string `json:"content,omitempty"` + URL *string `json:"url,omitempty"` + }{ + SHA: t.SHA, + Path: t.Path, + Mode: t.Mode, + Type: t.Type, + Size: t.Size, + Content: t.Content, + URL: t.URL, + }) +} + +// GetTree fetches the Tree object for a given sha hash from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/git/trees#get-a-tree +func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha) + if recursive { + u += "?recursive=1" + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Tree) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// createTree represents the body of a CreateTree request. +type createTree struct { + BaseTree string `json:"base_tree,omitempty"` + Entries []interface{} `json:"tree"` +} + +// CreateTree creates a new tree in a repository. If both a tree and a nested +// path modifying that tree are specified, it will overwrite the contents of +// that tree with the new path contents and write a new tree out. +// +// GitHub API docs: https://docs.github.com/en/rest/git/trees#create-a-tree +func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []*TreeEntry) (*Tree, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo) + + newEntries := make([]interface{}, 0, len(entries)) + for _, entry := range entries { + if entry.Content == nil && entry.SHA == nil { + newEntries = append(newEntries, treeEntryWithFileDelete{ + Path: entry.Path, + Mode: entry.Mode, + Type: entry.Type, + Size: entry.Size, + URL: entry.URL, + }) + continue + } + newEntries = append(newEntries, entry) + } + + body := &createTree{ + BaseTree: baseTree, + Entries: newEntries, + } + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + t := new(Tree) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/github-accessors.go b/vendor/github.com/google/go-github/v45/github/github-accessors.go new file mode 100644 index 0000000000..6da489c2cd --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/github-accessors.go @@ -0,0 +1,20039 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated by gen-accessors; DO NOT EDIT. +// Instead, please run "go generate ./..." as described here: +// https://github.com/google/go-github/blob/master/CONTRIBUTING.md#submitting-a-patch + +package github + +import ( + "encoding/json" + "time" +) + +// GetRetryAfter returns the RetryAfter field if it's non-nil, zero value otherwise. +func (a *AbuseRateLimitError) GetRetryAfter() time.Duration { + if a == nil || a.RetryAfter == nil { + return 0 + } + return *a.RetryAfter +} + +// GetGithubOwnedAllowed returns the GithubOwnedAllowed field if it's non-nil, zero value otherwise. +func (a *ActionsAllowed) GetGithubOwnedAllowed() bool { + if a == nil || a.GithubOwnedAllowed == nil { + return false + } + return *a.GithubOwnedAllowed +} + +// GetVerifiedAllowed returns the VerifiedAllowed field if it's non-nil, zero value otherwise. +func (a *ActionsAllowed) GetVerifiedAllowed() bool { + if a == nil || a.VerifiedAllowed == nil { + return false + } + return *a.VerifiedAllowed +} + +// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetAllowedActions() string { + if a == nil || a.AllowedActions == nil { + return "" + } + return *a.AllowedActions +} + +// GetEnabledRepositories returns the EnabledRepositories field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetEnabledRepositories() string { + if a == nil || a.EnabledRepositories == nil { + return "" + } + return *a.EnabledRepositories +} + +// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise. +func (a *ActionsPermissions) GetSelectedActionsURL() string { + if a == nil || a.SelectedActionsURL == nil { + return "" + } + return *a.SelectedActionsURL +} + +// GetAllowedActions returns the AllowedActions field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetAllowedActions() string { + if a == nil || a.AllowedActions == nil { + return "" + } + return *a.AllowedActions +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetEnabled() bool { + if a == nil || a.Enabled == nil { + return false + } + return *a.Enabled +} + +// GetSelectedActionsURL returns the SelectedActionsURL field if it's non-nil, zero value otherwise. +func (a *ActionsPermissionsRepository) GetSelectedActionsURL() string { + if a == nil || a.SelectedActionsURL == nil { + return "" + } + return *a.SelectedActionsURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AdminEnforcement) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetComments returns the Comments field. +func (a *AdminStats) GetComments() *CommentStats { + if a == nil { + return nil + } + return a.Comments +} + +// GetGists returns the Gists field. +func (a *AdminStats) GetGists() *GistStats { + if a == nil { + return nil + } + return a.Gists +} + +// GetHooks returns the Hooks field. +func (a *AdminStats) GetHooks() *HookStats { + if a == nil { + return nil + } + return a.Hooks +} + +// GetIssues returns the Issues field. +func (a *AdminStats) GetIssues() *IssueStats { + if a == nil { + return nil + } + return a.Issues +} + +// GetMilestones returns the Milestones field. +func (a *AdminStats) GetMilestones() *MilestoneStats { + if a == nil { + return nil + } + return a.Milestones +} + +// GetOrgs returns the Orgs field. +func (a *AdminStats) GetOrgs() *OrgStats { + if a == nil { + return nil + } + return a.Orgs +} + +// GetPages returns the Pages field. +func (a *AdminStats) GetPages() *PageStats { + if a == nil { + return nil + } + return a.Pages +} + +// GetPulls returns the Pulls field. +func (a *AdminStats) GetPulls() *PullStats { + if a == nil { + return nil + } + return a.Pulls +} + +// GetRepos returns the Repos field. +func (a *AdminStats) GetRepos() *RepoStats { + if a == nil { + return nil + } + return a.Repos +} + +// GetUsers returns the Users field. +func (a *AdminStats) GetUsers() *UserStats { + if a == nil { + return nil + } + return a.Users +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurity) GetStatus() string { + if a == nil || a.Status == nil { + return "" + } + return *a.Status +} + +// GetLastPushedDate returns the LastPushedDate field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurityCommittersBreakdown) GetLastPushedDate() string { + if a == nil || a.LastPushedDate == nil { + return "" + } + return *a.LastPushedDate +} + +// GetUserLogin returns the UserLogin field if it's non-nil, zero value otherwise. +func (a *AdvancedSecurityCommittersBreakdown) GetUserLogin() string { + if a == nil || a.UserLogin == nil { + return "" + } + return *a.UserLogin +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (a *AdvisoryIdentifier) GetType() string { + if a == nil || a.Type == nil { + return "" + } + return *a.Type +} + +// GetValue returns the Value field if it's non-nil, zero value otherwise. +func (a *AdvisoryIdentifier) GetValue() string { + if a == nil || a.Value == nil { + return "" + } + return *a.Value +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AdvisoryReference) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetFirstPatchedVersion returns the FirstPatchedVersion field. +func (a *AdvisoryVulnerability) GetFirstPatchedVersion() *FirstPatchedVersion { + if a == nil { + return nil + } + return a.FirstPatchedVersion +} + +// GetPackage returns the Package field. +func (a *AdvisoryVulnerability) GetPackage() *VulnerabilityPackage { + if a == nil { + return nil + } + return a.Package +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (a *AdvisoryVulnerability) GetSeverity() string { + if a == nil || a.Severity == nil { + return "" + } + return *a.Severity +} + +// GetVulnerableVersionRange returns the VulnerableVersionRange field if it's non-nil, zero value otherwise. +func (a *AdvisoryVulnerability) GetVulnerableVersionRange() string { + if a == nil || a.VulnerableVersionRange == nil { + return "" + } + return *a.VulnerableVersionRange +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetClosedAt() Timestamp { + if a == nil || a.ClosedAt == nil { + return Timestamp{} + } + return *a.ClosedAt +} + +// GetClosedBy returns the ClosedBy field. +func (a *Alert) GetClosedBy() *User { + if a == nil { + return nil + } + return a.ClosedBy +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetDismissedAt() Timestamp { + if a == nil || a.DismissedAt == nil { + return Timestamp{} + } + return *a.DismissedAt +} + +// GetDismissedBy returns the DismissedBy field. +func (a *Alert) GetDismissedBy() *User { + if a == nil { + return nil + } + return a.DismissedBy +} + +// GetDismissedReason returns the DismissedReason field if it's non-nil, zero value otherwise. +func (a *Alert) GetDismissedReason() string { + if a == nil || a.DismissedReason == nil { + return "" + } + return *a.DismissedReason +} + +// GetFixedAt returns the FixedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetFixedAt() Timestamp { + if a == nil || a.FixedAt == nil { + return Timestamp{} + } + return *a.FixedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *Alert) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetInstancesURL returns the InstancesURL field if it's non-nil, zero value otherwise. +func (a *Alert) GetInstancesURL() string { + if a == nil || a.InstancesURL == nil { + return "" + } + return *a.InstancesURL +} + +// GetMostRecentInstance returns the MostRecentInstance field. +func (a *Alert) GetMostRecentInstance() *MostRecentInstance { + if a == nil { + return nil + } + return a.MostRecentInstance +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (a *Alert) GetNumber() int { + if a == nil || a.Number == nil { + return 0 + } + return *a.Number +} + +// GetRepository returns the Repository field. +func (a *Alert) GetRepository() *Repository { + if a == nil { + return nil + } + return a.Repository +} + +// GetRule returns the Rule field. +func (a *Alert) GetRule() *Rule { + if a == nil { + return nil + } + return a.Rule +} + +// GetRuleDescription returns the RuleDescription field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleDescription() string { + if a == nil || a.RuleDescription == nil { + return "" + } + return *a.RuleDescription +} + +// GetRuleID returns the RuleID field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleID() string { + if a == nil || a.RuleID == nil { + return "" + } + return *a.RuleID +} + +// GetRuleSeverity returns the RuleSeverity field if it's non-nil, zero value otherwise. +func (a *Alert) GetRuleSeverity() string { + if a == nil || a.RuleSeverity == nil { + return "" + } + return *a.RuleSeverity +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (a *Alert) GetState() string { + if a == nil || a.State == nil { + return "" + } + return *a.State +} + +// GetTool returns the Tool field. +func (a *Alert) GetTool() *Tool { + if a == nil { + return nil + } + return a.Tool +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Alert) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Alert) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (a *AnalysesListOptions) GetRef() string { + if a == nil || a.Ref == nil { + return "" + } + return *a.Ref +} + +// GetSarifID returns the SarifID field if it's non-nil, zero value otherwise. +func (a *AnalysesListOptions) GetSarifID() string { + if a == nil || a.SarifID == nil { + return "" + } + return *a.SarifID +} + +// GetSSHKeyFingerprints returns the SSHKeyFingerprints map if it's non-nil, an empty map otherwise. +func (a *APIMeta) GetSSHKeyFingerprints() map[string]string { + if a == nil || a.SSHKeyFingerprints == nil { + return map[string]string{} + } + return a.SSHKeyFingerprints +} + +// GetVerifiablePasswordAuthentication returns the VerifiablePasswordAuthentication field if it's non-nil, zero value otherwise. +func (a *APIMeta) GetVerifiablePasswordAuthentication() bool { + if a == nil || a.VerifiablePasswordAuthentication == nil { + return false + } + return *a.VerifiablePasswordAuthentication +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *App) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (a *App) GetDescription() string { + if a == nil || a.Description == nil { + return "" + } + return *a.Description +} + +// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. +func (a *App) GetExternalURL() string { + if a == nil || a.ExternalURL == nil { + return "" + } + return *a.ExternalURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *App) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *App) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *App) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *App) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetOwner returns the Owner field. +func (a *App) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetPermissions returns the Permissions field. +func (a *App) GetPermissions() *InstallationPermissions { + if a == nil { + return nil + } + return a.Permissions +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (a *App) GetSlug() string { + if a == nil || a.Slug == nil { + return "" + } + return *a.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *App) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetClientSecret() string { + if a == nil || a.ClientSecret == nil { + return "" + } + return *a.ClientSecret +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetDescription() string { + if a == nil || a.Description == nil { + return "" + } + return *a.Description +} + +// GetExternalURL returns the ExternalURL field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetExternalURL() string { + if a == nil || a.ExternalURL == nil { + return "" + } + return *a.ExternalURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetHTMLURL() string { + if a == nil || a.HTMLURL == nil { + return "" + } + return *a.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetOwner returns the Owner field. +func (a *AppConfig) GetOwner() *User { + if a == nil { + return nil + } + return a.Owner +} + +// GetPEM returns the PEM field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetPEM() string { + if a == nil || a.PEM == nil { + return "" + } + return *a.PEM +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetSlug() string { + if a == nil || a.Slug == nil { + return "" + } + return *a.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetWebhookSecret returns the WebhookSecret field if it's non-nil, zero value otherwise. +func (a *AppConfig) GetWebhookSecret() string { + if a == nil || a.WebhookSecret == nil { + return "" + } + return *a.WebhookSecret +} + +// GetArchiveDownloadURL returns the ArchiveDownloadURL field if it's non-nil, zero value otherwise. +func (a *Artifact) GetArchiveDownloadURL() string { + if a == nil || a.ArchiveDownloadURL == nil { + return "" + } + return *a.ArchiveDownloadURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Artifact) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetExpired returns the Expired field if it's non-nil, zero value otherwise. +func (a *Artifact) GetExpired() bool { + if a == nil || a.Expired == nil { + return false + } + return *a.Expired +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (a *Artifact) GetExpiresAt() Timestamp { + if a == nil || a.ExpiresAt == nil { + return Timestamp{} + } + return *a.ExpiresAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Artifact) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *Artifact) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (a *Artifact) GetNodeID() string { + if a == nil || a.NodeID == nil { + return "" + } + return *a.NodeID +} + +// GetSizeInBytes returns the SizeInBytes field if it's non-nil, zero value otherwise. +func (a *Artifact) GetSizeInBytes() int64 { + if a == nil || a.SizeInBytes == nil { + return 0 + } + return *a.SizeInBytes +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (a *ArtifactList) GetTotalCount() int64 { + if a == nil || a.TotalCount == nil { + return 0 + } + return *a.TotalCount +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (a *Attachment) GetBody() string { + if a == nil || a.Body == nil { + return "" + } + return *a.Body +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Attachment) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (a *Attachment) GetTitle() string { + if a == nil || a.Title == nil { + return "" + } + return *a.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetAction() string { + if a == nil || a.Action == nil { + return "" + } + return *a.Action +} + +// GetActive returns the Active field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetActive() bool { + if a == nil || a.Active == nil { + return false + } + return *a.Active +} + +// GetActiveWas returns the ActiveWas field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetActiveWas() bool { + if a == nil || a.ActiveWas == nil { + return false + } + return *a.ActiveWas +} + +// GetActor returns the Actor field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetActor() string { + if a == nil || a.Actor == nil { + return "" + } + return *a.Actor +} + +// GetBlockedUser returns the BlockedUser field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetBlockedUser() string { + if a == nil || a.BlockedUser == nil { + return "" + } + return *a.BlockedUser +} + +// GetBusiness returns the Business field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetBusiness() string { + if a == nil || a.Business == nil { + return "" + } + return *a.Business +} + +// GetCancelledAt returns the CancelledAt field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetCancelledAt() Timestamp { + if a == nil || a.CancelledAt == nil { + return Timestamp{} + } + return *a.CancelledAt +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetCompletedAt() Timestamp { + if a == nil || a.CompletedAt == nil { + return Timestamp{} + } + return *a.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetConclusion() string { + if a == nil || a.Conclusion == nil { + return "" + } + return *a.Conclusion +} + +// GetConfig returns the Config field. +func (a *AuditEntry) GetConfig() *HookConfig { + if a == nil { + return nil + } + return a.Config +} + +// GetConfigWas returns the ConfigWas field. +func (a *AuditEntry) GetConfigWas() *HookConfig { + if a == nil { + return nil + } + return a.ConfigWas +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetContentType() string { + if a == nil || a.ContentType == nil { + return "" + } + return *a.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetDeployKeyFingerprint returns the DeployKeyFingerprint field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetDeployKeyFingerprint() string { + if a == nil || a.DeployKeyFingerprint == nil { + return "" + } + return *a.DeployKeyFingerprint +} + +// GetDocumentID returns the DocumentID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetDocumentID() string { + if a == nil || a.DocumentID == nil { + return "" + } + return *a.DocumentID +} + +// GetEmoji returns the Emoji field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetEmoji() string { + if a == nil || a.Emoji == nil { + return "" + } + return *a.Emoji +} + +// GetEnvironmentName returns the EnvironmentName field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetEnvironmentName() string { + if a == nil || a.EnvironmentName == nil { + return "" + } + return *a.EnvironmentName +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetEvent() string { + if a == nil || a.Event == nil { + return "" + } + return *a.Event +} + +// GetExplanation returns the Explanation field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetExplanation() string { + if a == nil || a.Explanation == nil { + return "" + } + return *a.Explanation +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetHeadBranch() string { + if a == nil || a.HeadBranch == nil { + return "" + } + return *a.HeadBranch +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetHeadSHA() string { + if a == nil || a.HeadSHA == nil { + return "" + } + return *a.HeadSHA +} + +// GetHookID returns the HookID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetHookID() int64 { + if a == nil || a.HookID == nil { + return 0 + } + return *a.HookID +} + +// GetIsHostedRunner returns the IsHostedRunner field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetIsHostedRunner() bool { + if a == nil || a.IsHostedRunner == nil { + return false + } + return *a.IsHostedRunner +} + +// GetJobName returns the JobName field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetJobName() string { + if a == nil || a.JobName == nil { + return "" + } + return *a.JobName +} + +// GetLimitedAvailability returns the LimitedAvailability field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetLimitedAvailability() bool { + if a == nil || a.LimitedAvailability == nil { + return false + } + return *a.LimitedAvailability +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetMessage() string { + if a == nil || a.Message == nil { + return "" + } + return *a.Message +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetOldUser returns the OldUser field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetOldUser() string { + if a == nil || a.OldUser == nil { + return "" + } + return *a.OldUser +} + +// GetOpenSSHPublicKey returns the OpenSSHPublicKey field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetOpenSSHPublicKey() string { + if a == nil || a.OpenSSHPublicKey == nil { + return "" + } + return *a.OpenSSHPublicKey +} + +// GetOrg returns the Org field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetOrg() string { + if a == nil || a.Org == nil { + return "" + } + return *a.Org +} + +// GetPreviousVisibility returns the PreviousVisibility field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetPreviousVisibility() string { + if a == nil || a.PreviousVisibility == nil { + return "" + } + return *a.PreviousVisibility +} + +// GetReadOnly returns the ReadOnly field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetReadOnly() string { + if a == nil || a.ReadOnly == nil { + return "" + } + return *a.ReadOnly +} + +// GetRepo returns the Repo field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetRepo() string { + if a == nil || a.Repo == nil { + return "" + } + return *a.Repo +} + +// GetRepository returns the Repository field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetRepository() string { + if a == nil || a.Repository == nil { + return "" + } + return *a.Repository +} + +// GetRepositoryPublic returns the RepositoryPublic field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetRepositoryPublic() bool { + if a == nil || a.RepositoryPublic == nil { + return false + } + return *a.RepositoryPublic +} + +// GetRunnerGroupID returns the RunnerGroupID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetRunnerGroupID() int64 { + if a == nil || a.RunnerGroupID == nil { + return 0 + } + return *a.RunnerGroupID +} + +// GetRunnerGroupName returns the RunnerGroupName field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetRunnerGroupName() string { + if a == nil || a.RunnerGroupName == nil { + return "" + } + return *a.RunnerGroupName +} + +// GetRunnerID returns the RunnerID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetRunnerID() int64 { + if a == nil || a.RunnerID == nil { + return 0 + } + return *a.RunnerID +} + +// GetRunnerName returns the RunnerName field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetRunnerName() string { + if a == nil || a.RunnerName == nil { + return "" + } + return *a.RunnerName +} + +// GetSourceVersion returns the SourceVersion field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetSourceVersion() string { + if a == nil || a.SourceVersion == nil { + return "" + } + return *a.SourceVersion +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetStartedAt() Timestamp { + if a == nil || a.StartedAt == nil { + return Timestamp{} + } + return *a.StartedAt +} + +// GetTargetLogin returns the TargetLogin field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTargetLogin() string { + if a == nil || a.TargetLogin == nil { + return "" + } + return *a.TargetLogin +} + +// GetTargetVersion returns the TargetVersion field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTargetVersion() string { + if a == nil || a.TargetVersion == nil { + return "" + } + return *a.TargetVersion +} + +// GetTeam returns the Team field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTeam() string { + if a == nil || a.Team == nil { + return "" + } + return *a.Team +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTimestamp() Timestamp { + if a == nil || a.Timestamp == nil { + return Timestamp{} + } + return *a.Timestamp +} + +// GetTransportProtocol returns the TransportProtocol field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTransportProtocol() int { + if a == nil || a.TransportProtocol == nil { + return 0 + } + return *a.TransportProtocol +} + +// GetTransportProtocolName returns the TransportProtocolName field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTransportProtocolName() string { + if a == nil || a.TransportProtocolName == nil { + return "" + } + return *a.TransportProtocolName +} + +// GetTriggerID returns the TriggerID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetTriggerID() int64 { + if a == nil || a.TriggerID == nil { + return 0 + } + return *a.TriggerID +} + +// GetUser returns the User field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetUser() string { + if a == nil || a.User == nil { + return "" + } + return *a.User +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetVisibility() string { + if a == nil || a.Visibility == nil { + return "" + } + return *a.Visibility +} + +// GetWorkflowID returns the WorkflowID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetWorkflowID() int64 { + if a == nil || a.WorkflowID == nil { + return 0 + } + return *a.WorkflowID +} + +// GetWorkflowRunID returns the WorkflowRunID field if it's non-nil, zero value otherwise. +func (a *AuditEntry) GetWorkflowRunID() int64 { + if a == nil || a.WorkflowRunID == nil { + return 0 + } + return *a.WorkflowRunID +} + +// GetApp returns the App field. +func (a *Authorization) GetApp() *AuthorizationApp { + if a == nil { + return nil + } + return a.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (a *Authorization) GetCreatedAt() Timestamp { + if a == nil || a.CreatedAt == nil { + return Timestamp{} + } + return *a.CreatedAt +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *Authorization) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (a *Authorization) GetHashedToken() string { + if a == nil || a.HashedToken == nil { + return "" + } + return *a.HashedToken +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Authorization) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *Authorization) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *Authorization) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (a *Authorization) GetToken() string { + if a == nil || a.Token == nil { + return "" + } + return *a.Token +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (a *Authorization) GetTokenLastEight() string { + if a == nil || a.TokenLastEight == nil { + return "" + } + return *a.TokenLastEight +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (a *Authorization) GetUpdatedAt() Timestamp { + if a == nil || a.UpdatedAt == nil { + return Timestamp{} + } + return *a.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *Authorization) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetUser returns the User field. +func (a *Authorization) GetUser() *User { + if a == nil { + return nil + } + return a.User +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetName() string { + if a == nil || a.Name == nil { + return "" + } + return *a.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (a *AuthorizationApp) GetURL() string { + if a == nil || a.URL == nil { + return "" + } + return *a.URL +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetClientID() string { + if a == nil || a.ClientID == nil { + return "" + } + return *a.ClientID +} + +// GetClientSecret returns the ClientSecret field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetClientSecret() string { + if a == nil || a.ClientSecret == nil { + return "" + } + return *a.ClientSecret +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *AuthorizationRequest) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetFingerprint() string { + if a == nil || a.Fingerprint == nil { + return "" + } + return *a.Fingerprint +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetNote() string { + if a == nil || a.Note == nil { + return "" + } + return *a.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (a *AuthorizationUpdateRequest) GetNoteURL() string { + if a == nil || a.NoteURL == nil { + return "" + } + return *a.NoteURL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (a *AuthorizedActorsOnly) GetFrom() bool { + if a == nil || a.From == nil { + return false + } + return *a.From +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (a *Autolink) GetID() int64 { + if a == nil || a.ID == nil { + return 0 + } + return *a.ID +} + +// GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise. +func (a *Autolink) GetKeyPrefix() string { + if a == nil || a.KeyPrefix == nil { + return "" + } + return *a.KeyPrefix +} + +// GetURLTemplate returns the URLTemplate field if it's non-nil, zero value otherwise. +func (a *Autolink) GetURLTemplate() string { + if a == nil || a.URLTemplate == nil { + return "" + } + return *a.URLTemplate +} + +// GetKeyPrefix returns the KeyPrefix field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetKeyPrefix() string { + if a == nil || a.KeyPrefix == nil { + return "" + } + return *a.KeyPrefix +} + +// GetURLTemplate returns the URLTemplate field if it's non-nil, zero value otherwise. +func (a *AutolinkOptions) GetURLTemplate() string { + if a == nil || a.URLTemplate == nil { + return "" + } + return *a.URLTemplate +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (a *AutoTriggerCheck) GetAppID() int64 { + if a == nil || a.AppID == nil { + return 0 + } + return *a.AppID +} + +// GetSetting returns the Setting field if it's non-nil, zero value otherwise. +func (a *AutoTriggerCheck) GetSetting() bool { + if a == nil || a.Setting == nil { + return false + } + return *a.Setting +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (b *Blob) GetContent() string { + if b == nil || b.Content == nil { + return "" + } + return *b.Content +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (b *Blob) GetEncoding() string { + if b == nil || b.Encoding == nil { + return "" + } + return *b.Encoding +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (b *Blob) GetNodeID() string { + if b == nil || b.NodeID == nil { + return "" + } + return *b.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (b *Blob) GetSHA() string { + if b == nil || b.SHA == nil { + return "" + } + return *b.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (b *Blob) GetSize() int { + if b == nil || b.Size == nil { + return 0 + } + return *b.Size +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (b *Blob) GetURL() string { + if b == nil || b.URL == nil { + return "" + } + return *b.URL +} + +// GetCommit returns the Commit field. +func (b *Branch) GetCommit() *RepositoryCommit { + if b == nil { + return nil + } + return b.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *Branch) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *Branch) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetCommit returns the Commit field. +func (b *BranchCommit) GetCommit() *Commit { + if b == nil { + return nil + } + return b.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *BranchCommit) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *BranchCommit) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetProtected returns the Protected field if it's non-nil, zero value otherwise. +func (b *BranchListOptions) GetProtected() bool { + if b == nil || b.Protected == nil { + return false + } + return *b.Protected +} + +// GetCustomBranchPolicies returns the CustomBranchPolicies field if it's non-nil, zero value otherwise. +func (b *BranchPolicy) GetCustomBranchPolicies() bool { + if b == nil || b.CustomBranchPolicies == nil { + return false + } + return *b.CustomBranchPolicies +} + +// GetProtectedBranches returns the ProtectedBranches field if it's non-nil, zero value otherwise. +func (b *BranchPolicy) GetProtectedBranches() bool { + if b == nil || b.ProtectedBranches == nil { + return false + } + return *b.ProtectedBranches +} + +// GetAdminEnforced returns the AdminEnforced field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAdminEnforced() bool { + if b == nil || b.AdminEnforced == nil { + return false + } + return *b.AdminEnforced +} + +// GetAllowDeletionsEnforcementLevel returns the AllowDeletionsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAllowDeletionsEnforcementLevel() string { + if b == nil || b.AllowDeletionsEnforcementLevel == nil { + return "" + } + return *b.AllowDeletionsEnforcementLevel +} + +// GetAllowForcePushesEnforcementLevel returns the AllowForcePushesEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAllowForcePushesEnforcementLevel() string { + if b == nil || b.AllowForcePushesEnforcementLevel == nil { + return "" + } + return *b.AllowForcePushesEnforcementLevel +} + +// GetAuthorizedActorsOnly returns the AuthorizedActorsOnly field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAuthorizedActorsOnly() bool { + if b == nil || b.AuthorizedActorsOnly == nil { + return false + } + return *b.AuthorizedActorsOnly +} + +// GetAuthorizedDismissalActorsOnly returns the AuthorizedDismissalActorsOnly field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetAuthorizedDismissalActorsOnly() bool { + if b == nil || b.AuthorizedDismissalActorsOnly == nil { + return false + } + return *b.AuthorizedDismissalActorsOnly +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetCreatedAt() Timestamp { + if b == nil || b.CreatedAt == nil { + return Timestamp{} + } + return *b.CreatedAt +} + +// GetDismissStaleReviewsOnPush returns the DismissStaleReviewsOnPush field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetDismissStaleReviewsOnPush() bool { + if b == nil || b.DismissStaleReviewsOnPush == nil { + return false + } + return *b.DismissStaleReviewsOnPush +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetID() int64 { + if b == nil || b.ID == nil { + return 0 + } + return *b.ID +} + +// GetIgnoreApprovalsFromContributors returns the IgnoreApprovalsFromContributors field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetIgnoreApprovalsFromContributors() bool { + if b == nil || b.IgnoreApprovalsFromContributors == nil { + return false + } + return *b.IgnoreApprovalsFromContributors +} + +// GetLinearHistoryRequirementEnforcementLevel returns the LinearHistoryRequirementEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetLinearHistoryRequirementEnforcementLevel() string { + if b == nil || b.LinearHistoryRequirementEnforcementLevel == nil { + return "" + } + return *b.LinearHistoryRequirementEnforcementLevel +} + +// GetMergeQueueEnforcementLevel returns the MergeQueueEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetMergeQueueEnforcementLevel() string { + if b == nil || b.MergeQueueEnforcementLevel == nil { + return "" + } + return *b.MergeQueueEnforcementLevel +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetName() string { + if b == nil || b.Name == nil { + return "" + } + return *b.Name +} + +// GetPullRequestReviewsEnforcementLevel returns the PullRequestReviewsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetPullRequestReviewsEnforcementLevel() string { + if b == nil || b.PullRequestReviewsEnforcementLevel == nil { + return "" + } + return *b.PullRequestReviewsEnforcementLevel +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRepositoryID() int64 { + if b == nil || b.RepositoryID == nil { + return 0 + } + return *b.RepositoryID +} + +// GetRequireCodeOwnerReview returns the RequireCodeOwnerReview field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequireCodeOwnerReview() bool { + if b == nil || b.RequireCodeOwnerReview == nil { + return false + } + return *b.RequireCodeOwnerReview +} + +// GetRequiredApprovingReviewCount returns the RequiredApprovingReviewCount field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredApprovingReviewCount() int { + if b == nil || b.RequiredApprovingReviewCount == nil { + return 0 + } + return *b.RequiredApprovingReviewCount +} + +// GetRequiredConversationResolutionLevel returns the RequiredConversationResolutionLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredConversationResolutionLevel() string { + if b == nil || b.RequiredConversationResolutionLevel == nil { + return "" + } + return *b.RequiredConversationResolutionLevel +} + +// GetRequiredDeploymentsEnforcementLevel returns the RequiredDeploymentsEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredDeploymentsEnforcementLevel() string { + if b == nil || b.RequiredDeploymentsEnforcementLevel == nil { + return "" + } + return *b.RequiredDeploymentsEnforcementLevel +} + +// GetRequiredStatusChecksEnforcementLevel returns the RequiredStatusChecksEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetRequiredStatusChecksEnforcementLevel() string { + if b == nil || b.RequiredStatusChecksEnforcementLevel == nil { + return "" + } + return *b.RequiredStatusChecksEnforcementLevel +} + +// GetSignatureRequirementEnforcementLevel returns the SignatureRequirementEnforcementLevel field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetSignatureRequirementEnforcementLevel() string { + if b == nil || b.SignatureRequirementEnforcementLevel == nil { + return "" + } + return *b.SignatureRequirementEnforcementLevel +} + +// GetStrictRequiredStatusChecksPolicy returns the StrictRequiredStatusChecksPolicy field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetStrictRequiredStatusChecksPolicy() bool { + if b == nil || b.StrictRequiredStatusChecksPolicy == nil { + return false + } + return *b.StrictRequiredStatusChecksPolicy +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRule) GetUpdatedAt() Timestamp { + if b == nil || b.UpdatedAt == nil { + return Timestamp{} + } + return *b.UpdatedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (b *BranchProtectionRuleEvent) GetAction() string { + if b == nil || b.Action == nil { + return "" + } + return *b.Action +} + +// GetChanges returns the Changes field. +func (b *BranchProtectionRuleEvent) GetChanges() *ProtectionChanges { + if b == nil { + return nil + } + return b.Changes +} + +// GetInstallation returns the Installation field. +func (b *BranchProtectionRuleEvent) GetInstallation() *Installation { + if b == nil { + return nil + } + return b.Installation +} + +// GetOrg returns the Org field. +func (b *BranchProtectionRuleEvent) GetOrg() *Organization { + if b == nil { + return nil + } + return b.Org +} + +// GetRepo returns the Repo field. +func (b *BranchProtectionRuleEvent) GetRepo() *Repository { + if b == nil { + return nil + } + return b.Repo +} + +// GetRule returns the Rule field. +func (b *BranchProtectionRuleEvent) GetRule() *BranchProtectionRule { + if b == nil { + return nil + } + return b.Rule +} + +// GetSender returns the Sender field. +func (b *BranchProtectionRuleEvent) GetSender() *User { + if b == nil { + return nil + } + return b.Sender +} + +// GetApp returns the App field. +func (c *CheckRun) GetApp() *App { + if c == nil { + return nil + } + return c.App +} + +// GetCheckSuite returns the CheckSuite field. +func (c *CheckRun) GetCheckSuite() *CheckSuite { + if c == nil { + return nil + } + return c.CheckSuite +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetCompletedAt() Timestamp { + if c == nil || c.CompletedAt == nil { + return Timestamp{} + } + return *c.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetDetailsURL() string { + if c == nil || c.DetailsURL == nil { + return "" + } + return *c.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetExternalID() string { + if c == nil || c.ExternalID == nil { + return "" + } + return *c.ExternalID +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetHeadSHA() string { + if c == nil || c.HeadSHA == nil { + return "" + } + return *c.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetOutput returns the Output field. +func (c *CheckRun) GetOutput() *CheckRunOutput { + if c == nil { + return nil + } + return c.Output +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetStartedAt() Timestamp { + if c == nil || c.StartedAt == nil { + return Timestamp{} + } + return *c.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CheckRun) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAnnotationLevel returns the AnnotationLevel field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetAnnotationLevel() string { + if c == nil || c.AnnotationLevel == nil { + return "" + } + return *c.AnnotationLevel +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetEndColumn() int { + if c == nil || c.EndColumn == nil { + return 0 + } + return *c.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetEndLine() int { + if c == nil || c.EndLine == nil { + return 0 + } + return *c.EndLine +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetMessage() string { + if c == nil || c.Message == nil { + return "" + } + return *c.Message +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetPath() string { + if c == nil || c.Path == nil { + return "" + } + return *c.Path +} + +// GetRawDetails returns the RawDetails field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetRawDetails() string { + if c == nil || c.RawDetails == nil { + return "" + } + return *c.RawDetails +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetStartColumn() int { + if c == nil || c.StartColumn == nil { + return 0 + } + return *c.StartColumn +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetStartLine() int { + if c == nil || c.StartLine == nil { + return 0 + } + return *c.StartLine +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (c *CheckRunAnnotation) GetTitle() string { + if c == nil || c.Title == nil { + return "" + } + return *c.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CheckRunEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetCheckRun returns the CheckRun field. +func (c *CheckRunEvent) GetCheckRun() *CheckRun { + if c == nil { + return nil + } + return c.CheckRun +} + +// GetInstallation returns the Installation field. +func (c *CheckRunEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CheckRunEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CheckRunEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetRequestedAction returns the RequestedAction field. +func (c *CheckRunEvent) GetRequestedAction() *RequestedAction { + if c == nil { + return nil + } + return c.RequestedAction +} + +// GetSender returns the Sender field. +func (c *CheckRunEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAlt returns the Alt field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetAlt() string { + if c == nil || c.Alt == nil { + return "" + } + return *c.Alt +} + +// GetCaption returns the Caption field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetCaption() string { + if c == nil || c.Caption == nil { + return "" + } + return *c.Caption +} + +// GetImageURL returns the ImageURL field if it's non-nil, zero value otherwise. +func (c *CheckRunImage) GetImageURL() string { + if c == nil || c.ImageURL == nil { + return "" + } + return *c.ImageURL +} + +// GetAnnotationsCount returns the AnnotationsCount field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetAnnotationsCount() int { + if c == nil || c.AnnotationsCount == nil { + return 0 + } + return *c.AnnotationsCount +} + +// GetAnnotationsURL returns the AnnotationsURL field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetAnnotationsURL() string { + if c == nil || c.AnnotationsURL == nil { + return "" + } + return *c.AnnotationsURL +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetSummary() string { + if c == nil || c.Summary == nil { + return "" + } + return *c.Summary +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetText() string { + if c == nil || c.Text == nil { + return "" + } + return *c.Text +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (c *CheckRunOutput) GetTitle() string { + if c == nil || c.Title == nil { + return "" + } + return *c.Title +} + +// GetAfterSHA returns the AfterSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetAfterSHA() string { + if c == nil || c.AfterSHA == nil { + return "" + } + return *c.AfterSHA +} + +// GetApp returns the App field. +func (c *CheckSuite) GetApp() *App { + if c == nil { + return nil + } + return c.App +} + +// GetBeforeSHA returns the BeforeSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetBeforeSHA() string { + if c == nil || c.BeforeSHA == nil { + return "" + } + return *c.BeforeSHA +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetHeadBranch() string { + if c == nil || c.HeadBranch == nil { + return "" + } + return *c.HeadBranch +} + +// GetHeadCommit returns the HeadCommit field. +func (c *CheckSuite) GetHeadCommit() *Commit { + if c == nil { + return nil + } + return c.HeadCommit +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetHeadSHA() string { + if c == nil || c.HeadSHA == nil { + return "" + } + return *c.HeadSHA +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetRepository returns the Repository field. +func (c *CheckSuite) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetUpdatedAt() Timestamp { + if c == nil || c.UpdatedAt == nil { + return Timestamp{} + } + return *c.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CheckSuite) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CheckSuiteEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetCheckSuite returns the CheckSuite field. +func (c *CheckSuiteEvent) GetCheckSuite() *CheckSuite { + if c == nil { + return nil + } + return c.CheckSuite +} + +// GetInstallation returns the Installation field. +func (c *CheckSuiteEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetOrg returns the Org field. +func (c *CheckSuiteEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRepo returns the Repo field. +func (c *CheckSuiteEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CheckSuiteEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetPreferences returns the Preferences field. +func (c *CheckSuitePreferenceResults) GetPreferences() *PreferenceList { + if c == nil { + return nil + } + return c.Preferences +} + +// GetRepository returns the Repository field. +func (c *CheckSuitePreferenceResults) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetBody() string { + if c == nil || c.Body == nil { + return "" + } + return *c.Body +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetKey() string { + if c == nil || c.Key == nil { + return "" + } + return *c.Key +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CodeOfConduct) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetPath() string { + if c == nil || c.Path == nil { + return "" + } + return *c.Path +} + +// GetRepository returns the Repository field. +func (c *CodeResult) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CodeResult) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetAlert returns the Alert field. +func (c *CodeScanningAlertEvent) GetAlert() *Alert { + if c == nil { + return nil + } + return c.Alert +} + +// GetCommitOID returns the CommitOID field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetCommitOID() string { + if c == nil || c.CommitOID == nil { + return "" + } + return *c.CommitOID +} + +// GetOrg returns the Org field. +func (c *CodeScanningAlertEvent) GetOrg() *Organization { + if c == nil { + return nil + } + return c.Org +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CodeScanningAlertEvent) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRepo returns the Repo field. +func (c *CodeScanningAlertEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CodeScanningAlertEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (c *CodeSearchResult) GetIncompleteResults() bool { + if c == nil || c.IncompleteResults == nil { + return false + } + return *c.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CodeSearchResult) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetCreatedAt() Timestamp { + if c == nil || c.CreatedAt == nil { + return Timestamp{} + } + return *c.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetInvitee returns the Invitee field. +func (c *CollaboratorInvitation) GetInvitee() *User { + if c == nil { + return nil + } + return c.Invitee +} + +// GetInviter returns the Inviter field. +func (c *CollaboratorInvitation) GetInviter() *User { + if c == nil { + return nil + } + return c.Inviter +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetPermissions() string { + if c == nil || c.Permissions == nil { + return "" + } + return *c.Permissions +} + +// GetRepo returns the Repo field. +func (c *CollaboratorInvitation) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CollaboratorInvitation) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetCommitURL() string { + if c == nil || c.CommitURL == nil { + return "" + } + return *c.CommitURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetRepositoryURL() string { + if c == nil || c.RepositoryURL == nil { + return "" + } + return *c.RepositoryURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetState() string { + if c == nil || c.State == nil { + return "" + } + return *c.State +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (c *CombinedStatus) GetTotalCount() int { + if c == nil || c.TotalCount == nil { + return 0 + } + return *c.TotalCount +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (c *Comment) GetCreatedAt() time.Time { + if c == nil || c.CreatedAt == nil { + return time.Time{} + } + return *c.CreatedAt +} + +// GetTotalCommitComments returns the TotalCommitComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalCommitComments() int { + if c == nil || c.TotalCommitComments == nil { + return 0 + } + return *c.TotalCommitComments +} + +// GetTotalGistComments returns the TotalGistComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalGistComments() int { + if c == nil || c.TotalGistComments == nil { + return 0 + } + return *c.TotalGistComments +} + +// GetTotalIssueComments returns the TotalIssueComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalIssueComments() int { + if c == nil || c.TotalIssueComments == nil { + return 0 + } + return *c.TotalIssueComments +} + +// GetTotalPullRequestComments returns the TotalPullRequestComments field if it's non-nil, zero value otherwise. +func (c *CommentStats) GetTotalPullRequestComments() int { + if c == nil || c.TotalPullRequestComments == nil { + return 0 + } + return *c.TotalPullRequestComments +} + +// GetAuthor returns the Author field. +func (c *Commit) GetAuthor() *CommitAuthor { + if c == nil { + return nil + } + return c.Author +} + +// GetCommentCount returns the CommentCount field if it's non-nil, zero value otherwise. +func (c *Commit) GetCommentCount() int { + if c == nil || c.CommentCount == nil { + return 0 + } + return *c.CommentCount +} + +// GetCommitter returns the Committer field. +func (c *Commit) GetCommitter() *CommitAuthor { + if c == nil { + return nil + } + return c.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Commit) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (c *Commit) GetMessage() string { + if c == nil || c.Message == nil { + return "" + } + return *c.Message +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *Commit) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *Commit) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetStats returns the Stats field. +func (c *Commit) GetStats() *CommitStats { + if c == nil { + return nil + } + return c.Stats +} + +// GetTree returns the Tree field. +func (c *Commit) GetTree() *Tree { + if c == nil { + return nil + } + return c.Tree +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Commit) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetVerification returns the Verification field. +func (c *Commit) GetVerification() *SignatureVerification { + if c == nil { + return nil + } + return c.Verification +} + +// GetDate returns the Date field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetDate() time.Time { + if c == nil || c.Date == nil { + return time.Time{} + } + return *c.Date +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CommitAuthor) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *CommitCommentEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetComment returns the Comment field. +func (c *CommitCommentEvent) GetComment() *RepositoryComment { + if c == nil { + return nil + } + return c.Comment +} + +// GetInstallation returns the Installation field. +func (c *CommitCommentEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetRepo returns the Repo field. +func (c *CommitCommentEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CommitCommentEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetAdditions() int { + if c == nil || c.Additions == nil { + return 0 + } + return *c.Additions +} + +// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetBlobURL() string { + if c == nil || c.BlobURL == nil { + return "" + } + return *c.BlobURL +} + +// GetChanges returns the Changes field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetChanges() int { + if c == nil || c.Changes == nil { + return 0 + } + return *c.Changes +} + +// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetContentsURL() string { + if c == nil || c.ContentsURL == nil { + return "" + } + return *c.ContentsURL +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetDeletions() int { + if c == nil || c.Deletions == nil { + return 0 + } + return *c.Deletions +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetFilename() string { + if c == nil || c.Filename == nil { + return "" + } + return *c.Filename +} + +// GetPatch returns the Patch field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetPatch() string { + if c == nil || c.Patch == nil { + return "" + } + return *c.Patch +} + +// GetPreviousFilename returns the PreviousFilename field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetPreviousFilename() string { + if c == nil || c.PreviousFilename == nil { + return "" + } + return *c.PreviousFilename +} + +// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetRawURL() string { + if c == nil || c.RawURL == nil { + return "" + } + return *c.RawURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CommitFile) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetAuthor returns the Author field. +func (c *CommitResult) GetAuthor() *User { + if c == nil { + return nil + } + return c.Author +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetCommentsURL() string { + if c == nil || c.CommentsURL == nil { + return "" + } + return *c.CommentsURL +} + +// GetCommit returns the Commit field. +func (c *CommitResult) GetCommit() *Commit { + if c == nil { + return nil + } + return c.Commit +} + +// GetCommitter returns the Committer field. +func (c *CommitResult) GetCommitter() *User { + if c == nil { + return nil + } + return c.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetRepository returns the Repository field. +func (c *CommitResult) GetRepository() *Repository { + if c == nil { + return nil + } + return c.Repository +} + +// GetScore returns the Score field. +func (c *CommitResult) GetScore() *float64 { + if c == nil { + return nil + } + return c.Score +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetSHA() string { + if c == nil || c.SHA == nil { + return "" + } + return *c.SHA +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CommitResult) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAheadBy returns the AheadBy field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetAheadBy() int { + if c == nil || c.AheadBy == nil { + return 0 + } + return *c.AheadBy +} + +// GetBaseCommit returns the BaseCommit field. +func (c *CommitsComparison) GetBaseCommit() *RepositoryCommit { + if c == nil { + return nil + } + return c.BaseCommit +} + +// GetBehindBy returns the BehindBy field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetBehindBy() int { + if c == nil || c.BehindBy == nil { + return 0 + } + return *c.BehindBy +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetDiffURL() string { + if c == nil || c.DiffURL == nil { + return "" + } + return *c.DiffURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetMergeBaseCommit returns the MergeBaseCommit field. +func (c *CommitsComparison) GetMergeBaseCommit() *RepositoryCommit { + if c == nil { + return nil + } + return c.MergeBaseCommit +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetPatchURL() string { + if c == nil || c.PatchURL == nil { + return "" + } + return *c.PatchURL +} + +// GetPermalinkURL returns the PermalinkURL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetPermalinkURL() string { + if c == nil || c.PermalinkURL == nil { + return "" + } + return *c.PermalinkURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetTotalCommits returns the TotalCommits field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetTotalCommits() int { + if c == nil || c.TotalCommits == nil { + return 0 + } + return *c.TotalCommits +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *CommitsComparison) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (c *CommitsSearchResult) GetIncompleteResults() bool { + if c == nil || c.IncompleteResults == nil { + return false + } + return *c.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CommitsSearchResult) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetAdditions() int { + if c == nil || c.Additions == nil { + return 0 + } + return *c.Additions +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetDeletions() int { + if c == nil || c.Deletions == nil { + return 0 + } + return *c.Deletions +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *CommitStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCodeOfConduct returns the CodeOfConduct field. +func (c *CommunityHealthFiles) GetCodeOfConduct() *Metric { + if c == nil { + return nil + } + return c.CodeOfConduct +} + +// GetCodeOfConductFile returns the CodeOfConductFile field. +func (c *CommunityHealthFiles) GetCodeOfConductFile() *Metric { + if c == nil { + return nil + } + return c.CodeOfConductFile +} + +// GetContributing returns the Contributing field. +func (c *CommunityHealthFiles) GetContributing() *Metric { + if c == nil { + return nil + } + return c.Contributing +} + +// GetIssueTemplate returns the IssueTemplate field. +func (c *CommunityHealthFiles) GetIssueTemplate() *Metric { + if c == nil { + return nil + } + return c.IssueTemplate +} + +// GetLicense returns the License field. +func (c *CommunityHealthFiles) GetLicense() *Metric { + if c == nil { + return nil + } + return c.License +} + +// GetPullRequestTemplate returns the PullRequestTemplate field. +func (c *CommunityHealthFiles) GetPullRequestTemplate() *Metric { + if c == nil { + return nil + } + return c.PullRequestTemplate +} + +// GetReadme returns the Readme field. +func (c *CommunityHealthFiles) GetReadme() *Metric { + if c == nil { + return nil + } + return c.Readme +} + +// GetContentReportsEnabled returns the ContentReportsEnabled field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetContentReportsEnabled() bool { + if c == nil || c.ContentReportsEnabled == nil { + return false + } + return *c.ContentReportsEnabled +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetDocumentation returns the Documentation field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetDocumentation() string { + if c == nil || c.Documentation == nil { + return "" + } + return *c.Documentation +} + +// GetFiles returns the Files field. +func (c *CommunityHealthMetrics) GetFiles() *CommunityHealthFiles { + if c == nil { + return nil + } + return c.Files +} + +// GetHealthPercentage returns the HealthPercentage field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetHealthPercentage() int { + if c == nil || c.HealthPercentage == nil { + return 0 + } + return *c.HealthPercentage +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (c *CommunityHealthMetrics) GetUpdatedAt() time.Time { + if c == nil || c.UpdatedAt == nil { + return time.Time{} + } + return *c.UpdatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetReference returns the Reference field if it's non-nil, zero value otherwise. +func (c *ContentReference) GetReference() string { + if c == nil || c.Reference == nil { + return "" + } + return *c.Reference +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (c *ContentReferenceEvent) GetAction() string { + if c == nil || c.Action == nil { + return "" + } + return *c.Action +} + +// GetContentReference returns the ContentReference field. +func (c *ContentReferenceEvent) GetContentReference() *ContentReference { + if c == nil { + return nil + } + return c.ContentReference +} + +// GetInstallation returns the Installation field. +func (c *ContentReferenceEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetRepo returns the Repo field. +func (c *ContentReferenceEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *ContentReferenceEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetAvatarURL() string { + if c == nil || c.AvatarURL == nil { + return "" + } + return *c.AvatarURL +} + +// GetContributions returns the Contributions field if it's non-nil, zero value otherwise. +func (c *Contributor) GetContributions() int { + if c == nil || c.Contributions == nil { + return 0 + } + return *c.Contributions +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetEventsURL() string { + if c == nil || c.EventsURL == nil { + return "" + } + return *c.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowersURL() string { + if c == nil || c.FollowersURL == nil { + return "" + } + return *c.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetFollowingURL() string { + if c == nil || c.FollowingURL == nil { + return "" + } + return *c.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGistsURL() string { + if c == nil || c.GistsURL == nil { + return "" + } + return *c.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetGravatarID() string { + if c == nil || c.GravatarID == nil { + return "" + } + return *c.GravatarID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetHTMLURL() string { + if c == nil || c.HTMLURL == nil { + return "" + } + return *c.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (c *Contributor) GetLogin() string { + if c == nil || c.Login == nil { + return "" + } + return *c.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *Contributor) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (c *Contributor) GetNodeID() string { + if c == nil || c.NodeID == nil { + return "" + } + return *c.NodeID +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetOrganizationsURL() string { + if c == nil || c.OrganizationsURL == nil { + return "" + } + return *c.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReceivedEventsURL() string { + if c == nil || c.ReceivedEventsURL == nil { + return "" + } + return *c.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetReposURL() string { + if c == nil || c.ReposURL == nil { + return "" + } + return *c.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSiteAdmin() bool { + if c == nil || c.SiteAdmin == nil { + return false + } + return *c.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetStarredURL() string { + if c == nil || c.StarredURL == nil { + return "" + } + return *c.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetSubscriptionsURL() string { + if c == nil || c.SubscriptionsURL == nil { + return "" + } + return *c.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (c *Contributor) GetType() string { + if c == nil || c.Type == nil { + return "" + } + return *c.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (c *Contributor) GetURL() string { + if c == nil || c.URL == nil { + return "" + } + return *c.URL +} + +// GetAuthor returns the Author field. +func (c *ContributorStats) GetAuthor() *Contributor { + if c == nil { + return nil + } + return c.Author +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (c *ContributorStats) GetTotal() int { + if c == nil || c.Total == nil { + return 0 + } + return *c.Total +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetCompletedAt() Timestamp { + if c == nil || c.CompletedAt == nil { + return Timestamp{} + } + return *c.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetConclusion() string { + if c == nil || c.Conclusion == nil { + return "" + } + return *c.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetDetailsURL() string { + if c == nil || c.DetailsURL == nil { + return "" + } + return *c.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetExternalID() string { + if c == nil || c.ExternalID == nil { + return "" + } + return *c.ExternalID +} + +// GetOutput returns the Output field. +func (c *CreateCheckRunOptions) GetOutput() *CheckRunOutput { + if c == nil { + return nil + } + return c.Output +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetStartedAt() Timestamp { + if c == nil || c.StartedAt == nil { + return Timestamp{} + } + return *c.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (c *CreateCheckRunOptions) GetStatus() string { + if c == nil || c.Status == nil { + return "" + } + return *c.Status +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (c *CreateCheckSuiteOptions) GetHeadBranch() string { + if c == nil || c.HeadBranch == nil { + return "" + } + return *c.HeadBranch +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetDescription() string { + if c == nil || c.Description == nil { + return "" + } + return *c.Description +} + +// GetInstallation returns the Installation field. +func (c *CreateEvent) GetInstallation() *Installation { + if c == nil { + return nil + } + return c.Installation +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetMasterBranch() string { + if c == nil || c.MasterBranch == nil { + return "" + } + return *c.MasterBranch +} + +// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetPusherType() string { + if c == nil || c.PusherType == nil { + return "" + } + return *c.PusherType +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetRef() string { + if c == nil || c.Ref == nil { + return "" + } + return *c.Ref +} + +// GetRefType returns the RefType field if it's non-nil, zero value otherwise. +func (c *CreateEvent) GetRefType() string { + if c == nil || c.RefType == nil { + return "" + } + return *c.RefType +} + +// GetRepo returns the Repo field. +func (c *CreateEvent) GetRepo() *Repository { + if c == nil { + return nil + } + return c.Repo +} + +// GetSender returns the Sender field. +func (c *CreateEvent) GetSender() *User { + if c == nil { + return nil + } + return c.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetEmail() string { + if c == nil || c.Email == nil { + return "" + } + return *c.Email +} + +// GetInviteeID returns the InviteeID field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetInviteeID() int64 { + if c == nil || c.InviteeID == nil { + return 0 + } + return *c.InviteeID +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (c *CreateOrgInvitationOptions) GetRole() string { + if c == nil || c.Role == nil { + return "" + } + return *c.Role +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if c == nil || c.AllowsPublicRepositories == nil { + return false + } + return *c.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (c *CreateRunnerGroupRequest) GetVisibility() string { + if c == nil || c.Visibility == nil { + return "" + } + return *c.Visibility +} + +// GetDeploymentBranchPolicy returns the DeploymentBranchPolicy field. +func (c *CreateUpdateEnvironment) GetDeploymentBranchPolicy() *BranchPolicy { + if c == nil { + return nil + } + return c.DeploymentBranchPolicy +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (c *CreateUpdateEnvironment) GetWaitTimer() int { + if c == nil || c.WaitTimer == nil { + return 0 + } + return *c.WaitTimer +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (c *CreateUserProjectOptions) GetBody() string { + if c == nil || c.Body == nil { + return "" + } + return *c.Body +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetID() int64 { + if c == nil || c.ID == nil { + return 0 + } + return *c.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (c *CustomRepoRoles) GetName() string { + if c == nil || c.Name == nil { + return "" + } + return *c.Name +} + +// GetInstallation returns the Installation field. +func (d *DeleteEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetPusherType returns the PusherType field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetPusherType() string { + if d == nil || d.PusherType == nil { + return "" + } + return *d.PusherType +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRefType returns the RefType field if it's non-nil, zero value otherwise. +func (d *DeleteEvent) GetRefType() string { + if d == nil || d.RefType == nil { + return "" + } + return *d.RefType +} + +// GetRepo returns the Repo field. +func (d *DeleteEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeleteEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DeployKeyEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetInstallation returns the Installation field. +func (d *DeployKeyEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetKey returns the Key field. +func (d *DeployKeyEvent) GetKey() *Key { + if d == nil { + return nil + } + return d.Key +} + +// GetOrganization returns the Organization field. +func (d *DeployKeyEvent) GetOrganization() *Organization { + if d == nil { + return nil + } + return d.Organization +} + +// GetRepo returns the Repo field. +func (d *DeployKeyEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeployKeyEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *Deployment) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetCreator returns the Creator field. +func (d *Deployment) GetCreator() *User { + if d == nil { + return nil + } + return d.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *Deployment) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *Deployment) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *Deployment) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *Deployment) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *Deployment) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (d *Deployment) GetSHA() string { + if d == nil || d.SHA == nil { + return "" + } + return *d.SHA +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetStatusesURL() string { + if d == nil || d.StatusesURL == nil { + return "" + } + return *d.StatusesURL +} + +// GetTask returns the Task field if it's non-nil, zero value otherwise. +func (d *Deployment) GetTask() string { + if d == nil || d.Task == nil { + return "" + } + return *d.Task +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *Deployment) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *Deployment) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetInstallation returns the Installation field. +func (d *DeploymentEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetRepo returns the Repo field. +func (d *DeploymentEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoMerge returns the AutoMerge field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetAutoMerge() bool { + if d == nil || d.AutoMerge == nil { + return false + } + return *d.AutoMerge +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetProductionEnvironment returns the ProductionEnvironment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetProductionEnvironment() bool { + if d == nil || d.ProductionEnvironment == nil { + return false + } + return *d.ProductionEnvironment +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetRef() string { + if d == nil || d.Ref == nil { + return "" + } + return *d.Ref +} + +// GetRequiredContexts returns the RequiredContexts field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetRequiredContexts() []string { + if d == nil || d.RequiredContexts == nil { + return nil + } + return *d.RequiredContexts +} + +// GetTask returns the Task field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetTask() string { + if d == nil || d.Task == nil { + return "" + } + return *d.Task +} + +// GetTransientEnvironment returns the TransientEnvironment field if it's non-nil, zero value otherwise. +func (d *DeploymentRequest) GetTransientEnvironment() bool { + if d == nil || d.TransientEnvironment == nil { + return false + } + return *d.TransientEnvironment +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetCreator returns the Creator field. +func (d *DeploymentStatus) GetCreator() *User { + if d == nil { + return nil + } + return d.Creator +} + +// GetDeploymentURL returns the DeploymentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetDeploymentURL() string { + if d == nil || d.DeploymentURL == nil { + return "" + } + return *d.DeploymentURL +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetEnvironmentURL() string { + if d == nil || d.EnvironmentURL == nil { + return "" + } + return *d.EnvironmentURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetLogURL() string { + if d == nil || d.LogURL == nil { + return "" + } + return *d.LogURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetTargetURL() string { + if d == nil || d.TargetURL == nil { + return "" + } + return *d.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatus) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetDeployment returns the Deployment field. +func (d *DeploymentStatusEvent) GetDeployment() *Deployment { + if d == nil { + return nil + } + return d.Deployment +} + +// GetDeploymentStatus returns the DeploymentStatus field. +func (d *DeploymentStatusEvent) GetDeploymentStatus() *DeploymentStatus { + if d == nil { + return nil + } + return d.DeploymentStatus +} + +// GetInstallation returns the Installation field. +func (d *DeploymentStatusEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetRepo returns the Repo field. +func (d *DeploymentStatusEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DeploymentStatusEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetAutoInactive returns the AutoInactive field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetAutoInactive() bool { + if d == nil || d.AutoInactive == nil { + return false + } + return *d.AutoInactive +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetEnvironment() string { + if d == nil || d.Environment == nil { + return "" + } + return *d.Environment +} + +// GetEnvironmentURL returns the EnvironmentURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetEnvironmentURL() string { + if d == nil || d.EnvironmentURL == nil { + return "" + } + return *d.EnvironmentURL +} + +// GetLogURL returns the LogURL field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetLogURL() string { + if d == nil || d.LogURL == nil { + return "" + } + return *d.LogURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DeploymentStatusRequest) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (d *Discussion) GetActiveLockReason() string { + if d == nil || d.ActiveLockReason == nil { + return "" + } + return *d.ActiveLockReason +} + +// GetAnswerChosenAt returns the AnswerChosenAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerChosenAt() Timestamp { + if d == nil || d.AnswerChosenAt == nil { + return Timestamp{} + } + return *d.AnswerChosenAt +} + +// GetAnswerChosenBy returns the AnswerChosenBy field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerChosenBy() string { + if d == nil || d.AnswerChosenBy == nil { + return "" + } + return *d.AnswerChosenBy +} + +// GetAnswerHTMLURL returns the AnswerHTMLURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAnswerHTMLURL() string { + if d == nil || d.AnswerHTMLURL == nil { + return "" + } + return *d.AnswerHTMLURL +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (d *Discussion) GetAuthorAssociation() string { + if d == nil || d.AuthorAssociation == nil { + return "" + } + return *d.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *Discussion) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (d *Discussion) GetComments() int { + if d == nil || d.Comments == nil { + return 0 + } + return *d.Comments +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDiscussionCategory returns the DiscussionCategory field. +func (d *Discussion) GetDiscussionCategory() *DiscussionCategory { + if d == nil { + return nil + } + return d.DiscussionCategory +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *Discussion) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (d *Discussion) GetLocked() bool { + if d == nil || d.Locked == nil { + return false + } + return *d.Locked +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *Discussion) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *Discussion) GetNumber() int { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (d *Discussion) GetRepositoryURL() string { + if d == nil || d.RepositoryURL == nil { + return "" + } + return *d.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *Discussion) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (d *Discussion) GetTitle() string { + if d == nil || d.Title == nil { + return "" + } + return *d.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *Discussion) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetUser returns the User field. +func (d *Discussion) GetUser() *User { + if d == nil { + return nil + } + return d.User +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetDescription() string { + if d == nil || d.Description == nil { + return "" + } + return *d.Description +} + +// GetEmoji returns the Emoji field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetEmoji() string { + if d == nil || d.Emoji == nil { + return "" + } + return *d.Emoji +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetID() int64 { + if d == nil || d.ID == nil { + return 0 + } + return *d.ID +} + +// GetIsAnswerable returns the IsAnswerable field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetIsAnswerable() bool { + if d == nil || d.IsAnswerable == nil { + return false + } + return *d.IsAnswerable +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetName() string { + if d == nil || d.Name == nil { + return "" + } + return *d.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetRepositoryID() int64 { + if d == nil || d.RepositoryID == nil { + return 0 + } + return *d.RepositoryID +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetSlug() string { + if d == nil || d.Slug == nil { + return "" + } + return *d.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionCategory) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetAuthor returns the Author field. +func (d *DiscussionComment) GetAuthor() *User { + if d == nil { + return nil + } + return d.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBodyHTML() string { + if d == nil || d.BodyHTML == nil { + return "" + } + return *d.BodyHTML +} + +// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetBodyVersion() string { + if d == nil || d.BodyVersion == nil { + return "" + } + return *d.BodyVersion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetCreatedAt() Timestamp { + if d == nil || d.CreatedAt == nil { + return Timestamp{} + } + return *d.CreatedAt +} + +// GetDiscussionURL returns the DiscussionURL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetDiscussionURL() string { + if d == nil || d.DiscussionURL == nil { + return "" + } + return *d.DiscussionURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetHTMLURL() string { + if d == nil || d.HTMLURL == nil { + return "" + } + return *d.HTMLURL +} + +// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetLastEditedAt() Timestamp { + if d == nil || d.LastEditedAt == nil { + return Timestamp{} + } + return *d.LastEditedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetNodeID() string { + if d == nil || d.NodeID == nil { + return "" + } + return *d.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetNumber() int { + if d == nil || d.Number == nil { + return 0 + } + return *d.Number +} + +// GetReactions returns the Reactions field. +func (d *DiscussionComment) GetReactions() *Reactions { + if d == nil { + return nil + } + return d.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetUpdatedAt() Timestamp { + if d == nil || d.UpdatedAt == nil { + return Timestamp{} + } + return *d.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (d *DiscussionComment) GetURL() string { + if d == nil || d.URL == nil { + return "" + } + return *d.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (d *DiscussionEvent) GetAction() string { + if d == nil || d.Action == nil { + return "" + } + return *d.Action +} + +// GetDiscussion returns the Discussion field. +func (d *DiscussionEvent) GetDiscussion() *Discussion { + if d == nil { + return nil + } + return d.Discussion +} + +// GetInstallation returns the Installation field. +func (d *DiscussionEvent) GetInstallation() *Installation { + if d == nil { + return nil + } + return d.Installation +} + +// GetOrg returns the Org field. +func (d *DiscussionEvent) GetOrg() *Organization { + if d == nil { + return nil + } + return d.Org +} + +// GetRepo returns the Repo field. +func (d *DiscussionEvent) GetRepo() *Repository { + if d == nil { + return nil + } + return d.Repo +} + +// GetSender returns the Sender field. +func (d *DiscussionEvent) GetSender() *User { + if d == nil { + return nil + } + return d.Sender +} + +// GetTeams returns the Teams field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetTeams() []string { + if d == nil || d.Teams == nil { + return nil + } + return *d.Teams +} + +// GetUsers returns the Users field if it's non-nil, zero value otherwise. +func (d *DismissalRestrictionsRequest) GetUsers() []string { + if d == nil || d.Users == nil { + return nil + } + return *d.Users +} + +// GetDismissalCommitID returns the DismissalCommitID field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetDismissalCommitID() string { + if d == nil || d.DismissalCommitID == nil { + return "" + } + return *d.DismissalCommitID +} + +// GetDismissalMessage returns the DismissalMessage field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetDismissalMessage() string { + if d == nil || d.DismissalMessage == nil { + return "" + } + return *d.DismissalMessage +} + +// GetReviewID returns the ReviewID field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetReviewID() int64 { + if d == nil || d.ReviewID == nil { + return 0 + } + return *d.ReviewID +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (d *DismissedReview) GetState() string { + if d == nil || d.State == nil { + return "" + } + return *d.State +} + +// GetClientPayload returns the ClientPayload field if it's non-nil, zero value otherwise. +func (d *DispatchRequestOptions) GetClientPayload() json.RawMessage { + if d == nil || d.ClientPayload == nil { + return json.RawMessage{} + } + return *d.ClientPayload +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetBody() string { + if d == nil || d.Body == nil { + return "" + } + return *d.Body +} + +// GetLine returns the Line field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetLine() int { + if d == nil || d.Line == nil { + return 0 + } + return *d.Line +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetPath() string { + if d == nil || d.Path == nil { + return "" + } + return *d.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetPosition() int { + if d == nil || d.Position == nil { + return 0 + } + return *d.Position +} + +// GetSide returns the Side field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetSide() string { + if d == nil || d.Side == nil { + return "" + } + return *d.Side +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetStartLine() int { + if d == nil || d.StartLine == nil { + return 0 + } + return *d.StartLine +} + +// GetStartSide returns the StartSide field if it's non-nil, zero value otherwise. +func (d *DraftReviewComment) GetStartSide() string { + if d == nil || d.StartSide == nil { + return "" + } + return *d.StartSide +} + +// GetRef returns the Ref field. +func (e *EditBase) GetRef() *EditRef { + if e == nil { + return nil + } + return e.Ref +} + +// GetSHA returns the SHA field. +func (e *EditBase) GetSHA() *EditSHA { + if e == nil { + return nil + } + return e.SHA +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditBody) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetBase returns the Base field. +func (e *EditChange) GetBase() *EditBase { + if e == nil { + return nil + } + return e.Base +} + +// GetBody returns the Body field. +func (e *EditChange) GetBody() *EditBody { + if e == nil { + return nil + } + return e.Body +} + +// GetRepo returns the Repo field. +func (e *EditChange) GetRepo() *EditRepo { + if e == nil { + return nil + } + return e.Repo +} + +// GetTitle returns the Title field. +func (e *EditChange) GetTitle() *EditTitle { + if e == nil { + return nil + } + return e.Title +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditRef) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetName returns the Name field. +func (e *EditRepo) GetName() *RepoName { + if e == nil { + return nil + } + return e.Name +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditSHA) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (e *EditTitle) GetFrom() string { + if e == nil || e.From == nil { + return "" + } + return *e.From +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetAvatarURL() string { + if e == nil || e.AvatarURL == nil { + return "" + } + return *e.AvatarURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetDescription() string { + if e == nil || e.Description == nil { + return "" + } + return *e.Description +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetHTMLURL() string { + if e == nil || e.HTMLURL == nil { + return "" + } + return *e.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetID() int { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetName() string { + if e == nil || e.Name == nil { + return "" + } + return *e.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetNodeID() string { + if e == nil || e.NodeID == nil { + return "" + } + return *e.NodeID +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetSlug() string { + if e == nil || e.Slug == nil { + return "" + } + return *e.Slug +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetWebsiteURL returns the WebsiteURL field if it's non-nil, zero value otherwise. +func (e *Enterprise) GetWebsiteURL() string { + if e == nil || e.WebsiteURL == nil { + return "" + } + return *e.WebsiteURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Environment) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetDeploymentBranchPolicy returns the DeploymentBranchPolicy field. +func (e *Environment) GetDeploymentBranchPolicy() *BranchPolicy { + if e == nil { + return nil + } + return e.DeploymentBranchPolicy +} + +// GetEnvironmentName returns the EnvironmentName field if it's non-nil, zero value otherwise. +func (e *Environment) GetEnvironmentName() string { + if e == nil || e.EnvironmentName == nil { + return "" + } + return *e.EnvironmentName +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (e *Environment) GetHTMLURL() string { + if e == nil || e.HTMLURL == nil { + return "" + } + return *e.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Environment) GetID() int64 { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (e *Environment) GetName() string { + if e == nil || e.Name == nil { + return "" + } + return *e.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (e *Environment) GetNodeID() string { + if e == nil || e.NodeID == nil { + return "" + } + return *e.NodeID +} + +// GetOwner returns the Owner field if it's non-nil, zero value otherwise. +func (e *Environment) GetOwner() string { + if e == nil || e.Owner == nil { + return "" + } + return *e.Owner +} + +// GetRepo returns the Repo field if it's non-nil, zero value otherwise. +func (e *Environment) GetRepo() string { + if e == nil || e.Repo == nil { + return "" + } + return *e.Repo +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *Environment) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (e *Environment) GetURL() string { + if e == nil || e.URL == nil { + return "" + } + return *e.URL +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (e *Environment) GetWaitTimer() int { + if e == nil || e.WaitTimer == nil { + return 0 + } + return *e.WaitTimer +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (e *EnvResponse) GetTotalCount() int { + if e == nil || e.TotalCount == nil { + return 0 + } + return *e.TotalCount +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *EnvReviewers) GetID() int64 { + if e == nil || e.ID == nil { + return 0 + } + return *e.ID +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (e *EnvReviewers) GetType() string { + if e == nil || e.Type == nil { + return "" + } + return *e.Type +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *ErrorBlock) GetCreatedAt() Timestamp { + if e == nil || e.CreatedAt == nil { + return Timestamp{} + } + return *e.CreatedAt +} + +// GetBlock returns the Block field. +func (e *ErrorResponse) GetBlock() *ErrorBlock { + if e == nil { + return nil + } + return e.Block +} + +// GetActor returns the Actor field. +func (e *Event) GetActor() *User { + if e == nil { + return nil + } + return e.Actor +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (e *Event) GetCreatedAt() time.Time { + if e == nil || e.CreatedAt == nil { + return time.Time{} + } + return *e.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (e *Event) GetID() string { + if e == nil || e.ID == nil { + return "" + } + return *e.ID +} + +// GetOrg returns the Org field. +func (e *Event) GetOrg() *Organization { + if e == nil { + return nil + } + return e.Org +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (e *Event) GetPublic() bool { + if e == nil || e.Public == nil { + return false + } + return *e.Public +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (e *Event) GetRawPayload() json.RawMessage { + if e == nil || e.RawPayload == nil { + return json.RawMessage{} + } + return *e.RawPayload +} + +// GetRepo returns the Repo field. +func (e *Event) GetRepo() *Repository { + if e == nil { + return nil + } + return e.Repo +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (e *Event) GetType() string { + if e == nil || e.Type == nil { + return "" + } + return *e.Type +} + +// GetGroupID returns the GroupID field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetGroupID() int64 { + if e == nil || e.GroupID == nil { + return 0 + } + return *e.GroupID +} + +// GetGroupName returns the GroupName field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetGroupName() string { + if e == nil || e.GroupName == nil { + return "" + } + return *e.GroupName +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (e *ExternalGroup) GetUpdatedAt() Timestamp { + if e == nil || e.UpdatedAt == nil { + return Timestamp{} + } + return *e.UpdatedAt +} + +// GetMemberEmail returns the MemberEmail field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberEmail() string { + if e == nil || e.MemberEmail == nil { + return "" + } + return *e.MemberEmail +} + +// GetMemberID returns the MemberID field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberID() int64 { + if e == nil || e.MemberID == nil { + return 0 + } + return *e.MemberID +} + +// GetMemberLogin returns the MemberLogin field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberLogin() string { + if e == nil || e.MemberLogin == nil { + return "" + } + return *e.MemberLogin +} + +// GetMemberName returns the MemberName field if it's non-nil, zero value otherwise. +func (e *ExternalGroupMember) GetMemberName() string { + if e == nil || e.MemberName == nil { + return "" + } + return *e.MemberName +} + +// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. +func (e *ExternalGroupTeam) GetTeamID() int64 { + if e == nil || e.TeamID == nil { + return 0 + } + return *e.TeamID +} + +// GetTeamName returns the TeamName field if it's non-nil, zero value otherwise. +func (e *ExternalGroupTeam) GetTeamName() string { + if e == nil || e.TeamName == nil { + return "" + } + return *e.TeamName +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (f *FeedLink) GetHRef() string { + if f == nil || f.HRef == nil { + return "" + } + return *f.HRef +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (f *FeedLink) GetType() string { + if f == nil || f.Type == nil { + return "" + } + return *f.Type +} + +// GetCurrentUser returns the CurrentUser field. +func (f *FeedLinks) GetCurrentUser() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUser +} + +// GetCurrentUserActor returns the CurrentUserActor field. +func (f *FeedLinks) GetCurrentUserActor() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserActor +} + +// GetCurrentUserOrganization returns the CurrentUserOrganization field. +func (f *FeedLinks) GetCurrentUserOrganization() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserOrganization +} + +// GetCurrentUserPublic returns the CurrentUserPublic field. +func (f *FeedLinks) GetCurrentUserPublic() *FeedLink { + if f == nil { + return nil + } + return f.CurrentUserPublic +} + +// GetTimeline returns the Timeline field. +func (f *FeedLinks) GetTimeline() *FeedLink { + if f == nil { + return nil + } + return f.Timeline +} + +// GetUser returns the User field. +func (f *FeedLinks) GetUser() *FeedLink { + if f == nil { + return nil + } + return f.User +} + +// GetCurrentUserActorURL returns the CurrentUserActorURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserActorURL() string { + if f == nil || f.CurrentUserActorURL == nil { + return "" + } + return *f.CurrentUserActorURL +} + +// GetCurrentUserOrganizationURL returns the CurrentUserOrganizationURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserOrganizationURL() string { + if f == nil || f.CurrentUserOrganizationURL == nil { + return "" + } + return *f.CurrentUserOrganizationURL +} + +// GetCurrentUserPublicURL returns the CurrentUserPublicURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserPublicURL() string { + if f == nil || f.CurrentUserPublicURL == nil { + return "" + } + return *f.CurrentUserPublicURL +} + +// GetCurrentUserURL returns the CurrentUserURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetCurrentUserURL() string { + if f == nil || f.CurrentUserURL == nil { + return "" + } + return *f.CurrentUserURL +} + +// GetLinks returns the Links field. +func (f *Feeds) GetLinks() *FeedLinks { + if f == nil { + return nil + } + return f.Links +} + +// GetTimelineURL returns the TimelineURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetTimelineURL() string { + if f == nil || f.TimelineURL == nil { + return "" + } + return *f.TimelineURL +} + +// GetUserURL returns the UserURL field if it's non-nil, zero value otherwise. +func (f *Feeds) GetUserURL() string { + if f == nil || f.UserURL == nil { + return "" + } + return *f.UserURL +} + +// GetIdentifier returns the Identifier field if it's non-nil, zero value otherwise. +func (f *FirstPatchedVersion) GetIdentifier() string { + if f == nil || f.Identifier == nil { + return "" + } + return *f.Identifier +} + +// GetForkee returns the Forkee field. +func (f *ForkEvent) GetForkee() *Repository { + if f == nil { + return nil + } + return f.Forkee +} + +// GetInstallation returns the Installation field. +func (f *ForkEvent) GetInstallation() *Installation { + if f == nil { + return nil + } + return f.Installation +} + +// GetRepo returns the Repo field. +func (f *ForkEvent) GetRepo() *Repository { + if f == nil { + return nil + } + return f.Repo +} + +// GetSender returns the Sender field. +func (f *ForkEvent) GetSender() *User { + if f == nil { + return nil + } + return f.Sender +} + +// GetPreviousTagName returns the PreviousTagName field if it's non-nil, zero value otherwise. +func (g *GenerateNotesOptions) GetPreviousTagName() string { + if g == nil || g.PreviousTagName == nil { + return "" + } + return *g.PreviousTagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (g *GenerateNotesOptions) GetTargetCommitish() string { + if g == nil || g.TargetCommitish == nil { + return "" + } + return *g.TargetCommitish +} + +// GetInclude returns the Include field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetInclude() string { + if g == nil || g.Include == nil { + return "" + } + return *g.Include +} + +// GetOrder returns the Order field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetOrder() string { + if g == nil || g.Order == nil { + return "" + } + return *g.Order +} + +// GetPhrase returns the Phrase field if it's non-nil, zero value otherwise. +func (g *GetAuditLogOptions) GetPhrase() string { + if g == nil || g.Phrase == nil { + return "" + } + return *g.Phrase +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (g *Gist) GetComments() int { + if g == nil || g.Comments == nil { + return 0 + } + return *g.Comments +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *Gist) GetCreatedAt() time.Time { + if g == nil || g.CreatedAt == nil { + return time.Time{} + } + return *g.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (g *Gist) GetDescription() string { + if g == nil || g.Description == nil { + return "" + } + return *g.Description +} + +// GetFiles returns the Files map if it's non-nil, an empty map otherwise. +func (g *Gist) GetFiles() map[GistFilename]GistFile { + if g == nil || g.Files == nil { + return map[GistFilename]GistFile{} + } + return g.Files +} + +// GetGitPullURL returns the GitPullURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetGitPullURL() string { + if g == nil || g.GitPullURL == nil { + return "" + } + return *g.GitPullURL +} + +// GetGitPushURL returns the GitPushURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetGitPushURL() string { + if g == nil || g.GitPushURL == nil { + return "" + } + return *g.GitPushURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (g *Gist) GetHTMLURL() string { + if g == nil || g.HTMLURL == nil { + return "" + } + return *g.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *Gist) GetID() string { + if g == nil || g.ID == nil { + return "" + } + return *g.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *Gist) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetOwner returns the Owner field. +func (g *Gist) GetOwner() *User { + if g == nil { + return nil + } + return g.Owner +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (g *Gist) GetPublic() bool { + if g == nil || g.Public == nil { + return false + } + return *g.Public +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *Gist) GetUpdatedAt() time.Time { + if g == nil || g.UpdatedAt == nil { + return time.Time{} + } + return *g.UpdatedAt +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (g *GistComment) GetBody() string { + if g == nil || g.Body == nil { + return "" + } + return *g.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GistComment) GetCreatedAt() time.Time { + if g == nil || g.CreatedAt == nil { + return time.Time{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GistComment) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistComment) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistComment) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetChangeStatus returns the ChangeStatus field. +func (g *GistCommit) GetChangeStatus() *CommitStats { + if g == nil { + return nil + } + return g.ChangeStatus +} + +// GetCommittedAt returns the CommittedAt field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetCommittedAt() Timestamp { + if g == nil || g.CommittedAt == nil { + return Timestamp{} + } + return *g.CommittedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistCommit) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (g *GistCommit) GetVersion() string { + if g == nil || g.Version == nil { + return "" + } + return *g.Version +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (g *GistFile) GetContent() string { + if g == nil || g.Content == nil { + return "" + } + return *g.Content +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (g *GistFile) GetFilename() string { + if g == nil || g.Filename == nil { + return "" + } + return *g.Filename +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (g *GistFile) GetLanguage() string { + if g == nil || g.Language == nil { + return "" + } + return *g.Language +} + +// GetRawURL returns the RawURL field if it's non-nil, zero value otherwise. +func (g *GistFile) GetRawURL() string { + if g == nil || g.RawURL == nil { + return "" + } + return *g.RawURL +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (g *GistFile) GetSize() int { + if g == nil || g.Size == nil { + return 0 + } + return *g.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GistFile) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GistFork) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GistFork) GetID() string { + if g == nil || g.ID == nil { + return "" + } + return *g.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (g *GistFork) GetNodeID() string { + if g == nil || g.NodeID == nil { + return "" + } + return *g.NodeID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *GistFork) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GistFork) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetUser returns the User field. +func (g *GistFork) GetUser() *User { + if g == nil { + return nil + } + return g.User +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetPrivateGists() int { + if g == nil || g.PrivateGists == nil { + return 0 + } + return *g.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetPublicGists() int { + if g == nil || g.PublicGists == nil { + return 0 + } + return *g.PublicGists +} + +// GetTotalGists returns the TotalGists field if it's non-nil, zero value otherwise. +func (g *GistStats) GetTotalGists() int { + if g == nil || g.TotalGists == nil { + return 0 + } + return *g.TotalGists +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (g *GitHubAppAuthorizationEvent) GetAction() string { + if g == nil || g.Action == nil { + return "" + } + return *g.Action +} + +// GetInstallation returns the Installation field. +func (g *GitHubAppAuthorizationEvent) GetInstallation() *Installation { + if g == nil { + return nil + } + return g.Installation +} + +// GetSender returns the Sender field. +func (g *GitHubAppAuthorizationEvent) GetSender() *User { + if g == nil { + return nil + } + return g.Sender +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (g *Gitignore) GetName() string { + if g == nil || g.Name == nil { + return "" + } + return *g.Name +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (g *Gitignore) GetSource() string { + if g == nil || g.Source == nil { + return "" + } + return *g.Source +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (g *GitObject) GetSHA() string { + if g == nil || g.SHA == nil { + return "" + } + return *g.SHA +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (g *GitObject) GetType() string { + if g == nil || g.Type == nil { + return "" + } + return *g.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *GitObject) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetInstallation returns the Installation field. +func (g *GollumEvent) GetInstallation() *Installation { + if g == nil { + return nil + } + return g.Installation +} + +// GetRepo returns the Repo field. +func (g *GollumEvent) GetRepo() *Repository { + if g == nil { + return nil + } + return g.Repo +} + +// GetSender returns the Sender field. +func (g *GollumEvent) GetSender() *User { + if g == nil { + return nil + } + return g.Sender +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (g *GPGEmail) GetEmail() string { + if g == nil || g.Email == nil { + return "" + } + return *g.Email +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (g *GPGEmail) GetVerified() bool { + if g == nil || g.Verified == nil { + return false + } + return *g.Verified +} + +// GetCanCertify returns the CanCertify field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanCertify() bool { + if g == nil || g.CanCertify == nil { + return false + } + return *g.CanCertify +} + +// GetCanEncryptComms returns the CanEncryptComms field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanEncryptComms() bool { + if g == nil || g.CanEncryptComms == nil { + return false + } + return *g.CanEncryptComms +} + +// GetCanEncryptStorage returns the CanEncryptStorage field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanEncryptStorage() bool { + if g == nil || g.CanEncryptStorage == nil { + return false + } + return *g.CanEncryptStorage +} + +// GetCanSign returns the CanSign field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCanSign() bool { + if g == nil || g.CanSign == nil { + return false + } + return *g.CanSign +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetCreatedAt() time.Time { + if g == nil || g.CreatedAt == nil { + return time.Time{} + } + return *g.CreatedAt +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetExpiresAt() time.Time { + if g == nil || g.ExpiresAt == nil { + return time.Time{} + } + return *g.ExpiresAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetKeyID() string { + if g == nil || g.KeyID == nil { + return "" + } + return *g.KeyID +} + +// GetPrimaryKeyID returns the PrimaryKeyID field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetPrimaryKeyID() int64 { + if g == nil || g.PrimaryKeyID == nil { + return 0 + } + return *g.PrimaryKeyID +} + +// GetPublicKey returns the PublicKey field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetPublicKey() string { + if g == nil || g.PublicKey == nil { + return "" + } + return *g.PublicKey +} + +// GetRawKey returns the RawKey field if it's non-nil, zero value otherwise. +func (g *GPGKey) GetRawKey() string { + if g == nil || g.RawKey == nil { + return "" + } + return *g.RawKey +} + +// GetApp returns the App field. +func (g *Grant) GetApp() *AuthorizationApp { + if g == nil { + return nil + } + return g.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (g *Grant) GetCreatedAt() Timestamp { + if g == nil || g.CreatedAt == nil { + return Timestamp{} + } + return *g.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (g *Grant) GetID() int64 { + if g == nil || g.ID == nil { + return 0 + } + return *g.ID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (g *Grant) GetUpdatedAt() Timestamp { + if g == nil || g.UpdatedAt == nil { + return Timestamp{} + } + return *g.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (g *Grant) GetURL() string { + if g == nil || g.URL == nil { + return "" + } + return *g.URL +} + +// GetAuthor returns the Author field. +func (h *HeadCommit) GetAuthor() *CommitAuthor { + if h == nil { + return nil + } + return h.Author +} + +// GetCommitter returns the Committer field. +func (h *HeadCommit) GetCommitter() *CommitAuthor { + if h == nil { + return nil + } + return h.Committer +} + +// GetDistinct returns the Distinct field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetDistinct() bool { + if h == nil || h.Distinct == nil { + return false + } + return *h.Distinct +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetID() string { + if h == nil || h.ID == nil { + return "" + } + return *h.ID +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetMessage() string { + if h == nil || h.Message == nil { + return "" + } + return *h.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetSHA() string { + if h == nil || h.SHA == nil { + return "" + } + return *h.SHA +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetTimestamp() Timestamp { + if h == nil || h.Timestamp == nil { + return Timestamp{} + } + return *h.Timestamp +} + +// GetTreeID returns the TreeID field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetTreeID() string { + if h == nil || h.TreeID == nil { + return "" + } + return *h.TreeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *HeadCommit) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetActive returns the Active field if it's non-nil, zero value otherwise. +func (h *Hook) GetActive() bool { + if h == nil || h.Active == nil { + return false + } + return *h.Active +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (h *Hook) GetCreatedAt() time.Time { + if h == nil || h.CreatedAt == nil { + return time.Time{} + } + return *h.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *Hook) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (h *Hook) GetName() string { + if h == nil || h.Name == nil { + return "" + } + return *h.Name +} + +// GetPingURL returns the PingURL field if it's non-nil, zero value otherwise. +func (h *Hook) GetPingURL() string { + if h == nil || h.PingURL == nil { + return "" + } + return *h.PingURL +} + +// GetTestURL returns the TestURL field if it's non-nil, zero value otherwise. +func (h *Hook) GetTestURL() string { + if h == nil || h.TestURL == nil { + return "" + } + return *h.TestURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (h *Hook) GetType() string { + if h == nil || h.Type == nil { + return "" + } + return *h.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (h *Hook) GetUpdatedAt() time.Time { + if h == nil || h.UpdatedAt == nil { + return time.Time{} + } + return *h.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *Hook) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetContentType() string { + if h == nil || h.ContentType == nil { + return "" + } + return *h.ContentType +} + +// GetInsecureSSL returns the InsecureSSL field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetInsecureSSL() string { + if h == nil || h.InsecureSSL == nil { + return "" + } + return *h.InsecureSSL +} + +// GetSecret returns the Secret field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetSecret() string { + if h == nil || h.Secret == nil { + return "" + } + return *h.Secret +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (h *HookConfig) GetURL() string { + if h == nil || h.URL == nil { + return "" + } + return *h.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetAction() string { + if h == nil || h.Action == nil { + return "" + } + return *h.Action +} + +// GetDeliveredAt returns the DeliveredAt field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetDeliveredAt() Timestamp { + if h == nil || h.DeliveredAt == nil { + return Timestamp{} + } + return *h.DeliveredAt +} + +// GetDuration returns the Duration field. +func (h *HookDelivery) GetDuration() *float64 { + if h == nil { + return nil + } + return h.Duration +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetEvent() string { + if h == nil || h.Event == nil { + return "" + } + return *h.Event +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetGUID() string { + if h == nil || h.GUID == nil { + return "" + } + return *h.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetID() int64 { + if h == nil || h.ID == nil { + return 0 + } + return *h.ID +} + +// GetInstallationID returns the InstallationID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetInstallationID() int64 { + if h == nil || h.InstallationID == nil { + return 0 + } + return *h.InstallationID +} + +// GetRedelivery returns the Redelivery field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetRedelivery() bool { + if h == nil || h.Redelivery == nil { + return false + } + return *h.Redelivery +} + +// GetRepositoryID returns the RepositoryID field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetRepositoryID() int64 { + if h == nil || h.RepositoryID == nil { + return 0 + } + return *h.RepositoryID +} + +// GetRequest returns the Request field. +func (h *HookDelivery) GetRequest() *HookRequest { + if h == nil { + return nil + } + return h.Request +} + +// GetResponse returns the Response field. +func (h *HookDelivery) GetResponse() *HookResponse { + if h == nil { + return nil + } + return h.Response +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetStatus() string { + if h == nil || h.Status == nil { + return "" + } + return *h.Status +} + +// GetStatusCode returns the StatusCode field if it's non-nil, zero value otherwise. +func (h *HookDelivery) GetStatusCode() int { + if h == nil || h.StatusCode == nil { + return 0 + } + return *h.StatusCode +} + +// GetHeaders returns the Headers map if it's non-nil, an empty map otherwise. +func (h *HookRequest) GetHeaders() map[string]string { + if h == nil || h.Headers == nil { + return map[string]string{} + } + return h.Headers +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (h *HookRequest) GetRawPayload() json.RawMessage { + if h == nil || h.RawPayload == nil { + return json.RawMessage{} + } + return *h.RawPayload +} + +// GetHeaders returns the Headers map if it's non-nil, an empty map otherwise. +func (h *HookResponse) GetHeaders() map[string]string { + if h == nil || h.Headers == nil { + return map[string]string{} + } + return h.Headers +} + +// GetRawPayload returns the RawPayload field if it's non-nil, zero value otherwise. +func (h *HookResponse) GetRawPayload() json.RawMessage { + if h == nil || h.RawPayload == nil { + return json.RawMessage{} + } + return *h.RawPayload +} + +// GetActiveHooks returns the ActiveHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetActiveHooks() int { + if h == nil || h.ActiveHooks == nil { + return 0 + } + return *h.ActiveHooks +} + +// GetInactiveHooks returns the InactiveHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetInactiveHooks() int { + if h == nil || h.InactiveHooks == nil { + return 0 + } + return *h.InactiveHooks +} + +// GetTotalHooks returns the TotalHooks field if it's non-nil, zero value otherwise. +func (h *HookStats) GetTotalHooks() int { + if h == nil || h.TotalHooks == nil { + return 0 + } + return *h.TotalHooks +} + +// GetGroupDescription returns the GroupDescription field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupDescription() string { + if i == nil || i.GroupDescription == nil { + return "" + } + return *i.GroupDescription +} + +// GetGroupID returns the GroupID field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupID() string { + if i == nil || i.GroupID == nil { + return "" + } + return *i.GroupID +} + +// GetGroupName returns the GroupName field if it's non-nil, zero value otherwise. +func (i *IDPGroup) GetGroupName() string { + if i == nil || i.GroupName == nil { + return "" + } + return *i.GroupName +} + +// GetAuthorsCount returns the AuthorsCount field if it's non-nil, zero value otherwise. +func (i *Import) GetAuthorsCount() int { + if i == nil || i.AuthorsCount == nil { + return 0 + } + return *i.AuthorsCount +} + +// GetAuthorsURL returns the AuthorsURL field if it's non-nil, zero value otherwise. +func (i *Import) GetAuthorsURL() string { + if i == nil || i.AuthorsURL == nil { + return "" + } + return *i.AuthorsURL +} + +// GetCommitCount returns the CommitCount field if it's non-nil, zero value otherwise. +func (i *Import) GetCommitCount() int { + if i == nil || i.CommitCount == nil { + return 0 + } + return *i.CommitCount +} + +// GetFailedStep returns the FailedStep field if it's non-nil, zero value otherwise. +func (i *Import) GetFailedStep() string { + if i == nil || i.FailedStep == nil { + return "" + } + return *i.FailedStep +} + +// GetHasLargeFiles returns the HasLargeFiles field if it's non-nil, zero value otherwise. +func (i *Import) GetHasLargeFiles() bool { + if i == nil || i.HasLargeFiles == nil { + return false + } + return *i.HasLargeFiles +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Import) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetHumanName returns the HumanName field if it's non-nil, zero value otherwise. +func (i *Import) GetHumanName() string { + if i == nil || i.HumanName == nil { + return "" + } + return *i.HumanName +} + +// GetLargeFilesCount returns the LargeFilesCount field if it's non-nil, zero value otherwise. +func (i *Import) GetLargeFilesCount() int { + if i == nil || i.LargeFilesCount == nil { + return 0 + } + return *i.LargeFilesCount +} + +// GetLargeFilesSize returns the LargeFilesSize field if it's non-nil, zero value otherwise. +func (i *Import) GetLargeFilesSize() int { + if i == nil || i.LargeFilesSize == nil { + return 0 + } + return *i.LargeFilesSize +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (i *Import) GetMessage() string { + if i == nil || i.Message == nil { + return "" + } + return *i.Message +} + +// GetPercent returns the Percent field if it's non-nil, zero value otherwise. +func (i *Import) GetPercent() int { + if i == nil || i.Percent == nil { + return 0 + } + return *i.Percent +} + +// GetPushPercent returns the PushPercent field if it's non-nil, zero value otherwise. +func (i *Import) GetPushPercent() int { + if i == nil || i.PushPercent == nil { + return 0 + } + return *i.PushPercent +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *Import) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (i *Import) GetStatus() string { + if i == nil || i.Status == nil { + return "" + } + return *i.Status +} + +// GetStatusText returns the StatusText field if it's non-nil, zero value otherwise. +func (i *Import) GetStatusText() string { + if i == nil || i.StatusText == nil { + return "" + } + return *i.StatusText +} + +// GetTFVCProject returns the TFVCProject field if it's non-nil, zero value otherwise. +func (i *Import) GetTFVCProject() string { + if i == nil || i.TFVCProject == nil { + return "" + } + return *i.TFVCProject +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *Import) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUseLFS returns the UseLFS field if it's non-nil, zero value otherwise. +func (i *Import) GetUseLFS() string { + if i == nil || i.UseLFS == nil { + return "" + } + return *i.UseLFS +} + +// GetVCS returns the VCS field if it's non-nil, zero value otherwise. +func (i *Import) GetVCS() string { + if i == nil || i.VCS == nil { + return "" + } + return *i.VCS +} + +// GetVCSPassword returns the VCSPassword field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSPassword() string { + if i == nil || i.VCSPassword == nil { + return "" + } + return *i.VCSPassword +} + +// GetVCSURL returns the VCSURL field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSURL() string { + if i == nil || i.VCSURL == nil { + return "" + } + return *i.VCSURL +} + +// GetVCSUsername returns the VCSUsername field if it's non-nil, zero value otherwise. +func (i *Import) GetVCSUsername() string { + if i == nil || i.VCSUsername == nil { + return "" + } + return *i.VCSUsername +} + +// GetAccessTokensURL returns the AccessTokensURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetAccessTokensURL() string { + if i == nil || i.AccessTokensURL == nil { + return "" + } + return *i.AccessTokensURL +} + +// GetAccount returns the Account field. +func (i *Installation) GetAccount() *User { + if i == nil { + return nil + } + return i.Account +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (i *Installation) GetAppID() int64 { + if i == nil || i.AppID == nil { + return 0 + } + return *i.AppID +} + +// GetAppSlug returns the AppSlug field if it's non-nil, zero value otherwise. +func (i *Installation) GetAppSlug() string { + if i == nil || i.AppSlug == nil { + return "" + } + return *i.AppSlug +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetCreatedAt() Timestamp { + if i == nil || i.CreatedAt == nil { + return Timestamp{} + } + return *i.CreatedAt +} + +// GetHasMultipleSingleFiles returns the HasMultipleSingleFiles field if it's non-nil, zero value otherwise. +func (i *Installation) GetHasMultipleSingleFiles() bool { + if i == nil || i.HasMultipleSingleFiles == nil { + return false + } + return *i.HasMultipleSingleFiles +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Installation) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Installation) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetPermissions returns the Permissions field. +func (i *Installation) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (i *Installation) GetRepositoriesURL() string { + if i == nil || i.RepositoriesURL == nil { + return "" + } + return *i.RepositoriesURL +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (i *Installation) GetRepositorySelection() string { + if i == nil || i.RepositorySelection == nil { + return "" + } + return *i.RepositorySelection +} + +// GetSingleFileName returns the SingleFileName field if it's non-nil, zero value otherwise. +func (i *Installation) GetSingleFileName() string { + if i == nil || i.SingleFileName == nil { + return "" + } + return *i.SingleFileName +} + +// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetSuspendedAt() Timestamp { + if i == nil || i.SuspendedAt == nil { + return Timestamp{} + } + return *i.SuspendedAt +} + +// GetSuspendedBy returns the SuspendedBy field. +func (i *Installation) GetSuspendedBy() *User { + if i == nil { + return nil + } + return i.SuspendedBy +} + +// GetTargetID returns the TargetID field if it's non-nil, zero value otherwise. +func (i *Installation) GetTargetID() int64 { + if i == nil || i.TargetID == nil { + return 0 + } + return *i.TargetID +} + +// GetTargetType returns the TargetType field if it's non-nil, zero value otherwise. +func (i *Installation) GetTargetType() string { + if i == nil || i.TargetType == nil { + return "" + } + return *i.TargetType +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *Installation) GetUpdatedAt() Timestamp { + if i == nil || i.UpdatedAt == nil { + return Timestamp{} + } + return *i.UpdatedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetInstallation returns the Installation field. +func (i *InstallationEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetSender returns the Sender field. +func (i *InstallationEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetActions returns the Actions field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetActions() string { + if i == nil || i.Actions == nil { + return "" + } + return *i.Actions +} + +// GetAdministration returns the Administration field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetAdministration() string { + if i == nil || i.Administration == nil { + return "" + } + return *i.Administration +} + +// GetBlocking returns the Blocking field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetBlocking() string { + if i == nil || i.Blocking == nil { + return "" + } + return *i.Blocking +} + +// GetChecks returns the Checks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetChecks() string { + if i == nil || i.Checks == nil { + return "" + } + return *i.Checks +} + +// GetContentReferences returns the ContentReferences field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetContentReferences() string { + if i == nil || i.ContentReferences == nil { + return "" + } + return *i.ContentReferences +} + +// GetContents returns the Contents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetContents() string { + if i == nil || i.Contents == nil { + return "" + } + return *i.Contents +} + +// GetDeployments returns the Deployments field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetDeployments() string { + if i == nil || i.Deployments == nil { + return "" + } + return *i.Deployments +} + +// GetEmails returns the Emails field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetEmails() string { + if i == nil || i.Emails == nil { + return "" + } + return *i.Emails +} + +// GetEnvironments returns the Environments field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetEnvironments() string { + if i == nil || i.Environments == nil { + return "" + } + return *i.Environments +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetFollowers() string { + if i == nil || i.Followers == nil { + return "" + } + return *i.Followers +} + +// GetIssues returns the Issues field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetIssues() string { + if i == nil || i.Issues == nil { + return "" + } + return *i.Issues +} + +// GetMembers returns the Members field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMembers() string { + if i == nil || i.Members == nil { + return "" + } + return *i.Members +} + +// GetMetadata returns the Metadata field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetMetadata() string { + if i == nil || i.Metadata == nil { + return "" + } + return *i.Metadata +} + +// GetOrganizationAdministration returns the OrganizationAdministration field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationAdministration() string { + if i == nil || i.OrganizationAdministration == nil { + return "" + } + return *i.OrganizationAdministration +} + +// GetOrganizationHooks returns the OrganizationHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationHooks() string { + if i == nil || i.OrganizationHooks == nil { + return "" + } + return *i.OrganizationHooks +} + +// GetOrganizationPlan returns the OrganizationPlan field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPlan() string { + if i == nil || i.OrganizationPlan == nil { + return "" + } + return *i.OrganizationPlan +} + +// GetOrganizationPreReceiveHooks returns the OrganizationPreReceiveHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationPreReceiveHooks() string { + if i == nil || i.OrganizationPreReceiveHooks == nil { + return "" + } + return *i.OrganizationPreReceiveHooks +} + +// GetOrganizationProjects returns the OrganizationProjects field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationProjects() string { + if i == nil || i.OrganizationProjects == nil { + return "" + } + return *i.OrganizationProjects +} + +// GetOrganizationSecrets returns the OrganizationSecrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationSecrets() string { + if i == nil || i.OrganizationSecrets == nil { + return "" + } + return *i.OrganizationSecrets +} + +// GetOrganizationSelfHostedRunners returns the OrganizationSelfHostedRunners field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationSelfHostedRunners() string { + if i == nil || i.OrganizationSelfHostedRunners == nil { + return "" + } + return *i.OrganizationSelfHostedRunners +} + +// GetOrganizationUserBlocking returns the OrganizationUserBlocking field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetOrganizationUserBlocking() string { + if i == nil || i.OrganizationUserBlocking == nil { + return "" + } + return *i.OrganizationUserBlocking +} + +// GetPackages returns the Packages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPackages() string { + if i == nil || i.Packages == nil { + return "" + } + return *i.Packages +} + +// GetPages returns the Pages field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPages() string { + if i == nil || i.Pages == nil { + return "" + } + return *i.Pages +} + +// GetPullRequests returns the PullRequests field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetPullRequests() string { + if i == nil || i.PullRequests == nil { + return "" + } + return *i.PullRequests +} + +// GetRepositoryHooks returns the RepositoryHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryHooks() string { + if i == nil || i.RepositoryHooks == nil { + return "" + } + return *i.RepositoryHooks +} + +// GetRepositoryPreReceiveHooks returns the RepositoryPreReceiveHooks field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryPreReceiveHooks() string { + if i == nil || i.RepositoryPreReceiveHooks == nil { + return "" + } + return *i.RepositoryPreReceiveHooks +} + +// GetRepositoryProjects returns the RepositoryProjects field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetRepositoryProjects() string { + if i == nil || i.RepositoryProjects == nil { + return "" + } + return *i.RepositoryProjects +} + +// GetSecrets returns the Secrets field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecrets() string { + if i == nil || i.Secrets == nil { + return "" + } + return *i.Secrets +} + +// GetSecretScanningAlerts returns the SecretScanningAlerts field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecretScanningAlerts() string { + if i == nil || i.SecretScanningAlerts == nil { + return "" + } + return *i.SecretScanningAlerts +} + +// GetSecurityEvents returns the SecurityEvents field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSecurityEvents() string { + if i == nil || i.SecurityEvents == nil { + return "" + } + return *i.SecurityEvents +} + +// GetSingleFile returns the SingleFile field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetSingleFile() string { + if i == nil || i.SingleFile == nil { + return "" + } + return *i.SingleFile +} + +// GetStatuses returns the Statuses field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetStatuses() string { + if i == nil || i.Statuses == nil { + return "" + } + return *i.Statuses +} + +// GetTeamDiscussions returns the TeamDiscussions field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetTeamDiscussions() string { + if i == nil || i.TeamDiscussions == nil { + return "" + } + return *i.TeamDiscussions +} + +// GetVulnerabilityAlerts returns the VulnerabilityAlerts field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetVulnerabilityAlerts() string { + if i == nil || i.VulnerabilityAlerts == nil { + return "" + } + return *i.VulnerabilityAlerts +} + +// GetWorkflows returns the Workflows field if it's non-nil, zero value otherwise. +func (i *InstallationPermissions) GetWorkflows() string { + if i == nil || i.Workflows == nil { + return "" + } + return *i.Workflows +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *InstallationRepositoriesEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetInstallation returns the Installation field. +func (i *InstallationRepositoriesEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetRepositorySelection returns the RepositorySelection field if it's non-nil, zero value otherwise. +func (i *InstallationRepositoriesEvent) GetRepositorySelection() string { + if i == nil || i.RepositorySelection == nil { + return "" + } + return *i.RepositorySelection +} + +// GetSender returns the Sender field. +func (i *InstallationRepositoriesEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (i *InstallationToken) GetExpiresAt() time.Time { + if i == nil || i.ExpiresAt == nil { + return time.Time{} + } + return *i.ExpiresAt +} + +// GetPermissions returns the Permissions field. +func (i *InstallationToken) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (i *InstallationToken) GetToken() string { + if i == nil || i.Token == nil { + return "" + } + return *i.Token +} + +// GetPermissions returns the Permissions field. +func (i *InstallationTokenOptions) GetPermissions() *InstallationPermissions { + if i == nil { + return nil + } + return i.Permissions +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetExpiresAt() Timestamp { + if i == nil || i.ExpiresAt == nil { + return Timestamp{} + } + return *i.ExpiresAt +} + +// GetLimit returns the Limit field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetLimit() string { + if i == nil || i.Limit == nil { + return "" + } + return *i.Limit +} + +// GetOrigin returns the Origin field if it's non-nil, zero value otherwise. +func (i *InteractionRestriction) GetOrigin() string { + if i == nil || i.Origin == nil { + return "" + } + return *i.Origin +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Invitation) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (i *Invitation) GetEmail() string { + if i == nil || i.Email == nil { + return "" + } + return *i.Email +} + +// GetFailedAt returns the FailedAt field if it's non-nil, zero value otherwise. +func (i *Invitation) GetFailedAt() Timestamp { + if i == nil || i.FailedAt == nil { + return Timestamp{} + } + return *i.FailedAt +} + +// GetFailedReason returns the FailedReason field if it's non-nil, zero value otherwise. +func (i *Invitation) GetFailedReason() string { + if i == nil || i.FailedReason == nil { + return "" + } + return *i.FailedReason +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Invitation) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetInvitationTeamURL returns the InvitationTeamURL field if it's non-nil, zero value otherwise. +func (i *Invitation) GetInvitationTeamURL() string { + if i == nil || i.InvitationTeamURL == nil { + return "" + } + return *i.InvitationTeamURL +} + +// GetInviter returns the Inviter field. +func (i *Invitation) GetInviter() *User { + if i == nil { + return nil + } + return i.Inviter +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (i *Invitation) GetLogin() string { + if i == nil || i.Login == nil { + return "" + } + return *i.Login +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Invitation) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (i *Invitation) GetRole() string { + if i == nil || i.Role == nil { + return "" + } + return *i.Role +} + +// GetTeamCount returns the TeamCount field if it's non-nil, zero value otherwise. +func (i *Invitation) GetTeamCount() int { + if i == nil || i.TeamCount == nil { + return 0 + } + return *i.TeamCount +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (i *Issue) GetActiveLockReason() string { + if i == nil || i.ActiveLockReason == nil { + return "" + } + return *i.ActiveLockReason +} + +// GetAssignee returns the Assignee field. +func (i *Issue) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (i *Issue) GetAuthorAssociation() string { + if i == nil || i.AuthorAssociation == nil { + return "" + } + return *i.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *Issue) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetClosedAt() time.Time { + if i == nil || i.ClosedAt == nil { + return time.Time{} + } + return *i.ClosedAt +} + +// GetClosedBy returns the ClosedBy field. +func (i *Issue) GetClosedBy() *User { + if i == nil { + return nil + } + return i.ClosedBy +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (i *Issue) GetComments() int { + if i == nil || i.Comments == nil { + return 0 + } + return *i.Comments +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetCommentsURL() string { + if i == nil || i.CommentsURL == nil { + return "" + } + return *i.CommentsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetEventsURL() string { + if i == nil || i.EventsURL == nil { + return "" + } + return *i.EventsURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *Issue) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetLabelsURL() string { + if i == nil || i.LabelsURL == nil { + return "" + } + return *i.LabelsURL +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (i *Issue) GetLocked() bool { + if i == nil || i.Locked == nil { + return false + } + return *i.Locked +} + +// GetMilestone returns the Milestone field. +func (i *Issue) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *Issue) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (i *Issue) GetNumber() int { + if i == nil || i.Number == nil { + return 0 + } + return *i.Number +} + +// GetPullRequestLinks returns the PullRequestLinks field. +func (i *Issue) GetPullRequestLinks() *PullRequestLinks { + if i == nil { + return nil + } + return i.PullRequestLinks +} + +// GetReactions returns the Reactions field. +func (i *Issue) GetReactions() *Reactions { + if i == nil { + return nil + } + return i.Reactions +} + +// GetRepository returns the Repository field. +func (i *Issue) GetRepository() *Repository { + if i == nil { + return nil + } + return i.Repository +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *Issue) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (i *Issue) GetState() string { + if i == nil || i.State == nil { + return "" + } + return *i.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (i *Issue) GetTitle() string { + if i == nil || i.Title == nil { + return "" + } + return *i.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *Issue) GetUpdatedAt() time.Time { + if i == nil || i.UpdatedAt == nil { + return time.Time{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *Issue) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUser returns the User field. +func (i *Issue) GetUser() *User { + if i == nil { + return nil + } + return i.User +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetAuthorAssociation() string { + if i == nil || i.AuthorAssociation == nil { + return "" + } + return *i.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetHTMLURL() string { + if i == nil || i.HTMLURL == nil { + return "" + } + return *i.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetIssueURL() string { + if i == nil || i.IssueURL == nil { + return "" + } + return *i.IssueURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetNodeID() string { + if i == nil || i.NodeID == nil { + return "" + } + return *i.NodeID +} + +// GetReactions returns the Reactions field. +func (i *IssueComment) GetReactions() *Reactions { + if i == nil { + return nil + } + return i.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetUpdatedAt() time.Time { + if i == nil || i.UpdatedAt == nil { + return time.Time{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueComment) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetUser returns the User field. +func (i *IssueComment) GetUser() *User { + if i == nil { + return nil + } + return i.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssueCommentEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetChanges returns the Changes field. +func (i *IssueCommentEvent) GetChanges() *EditChange { + if i == nil { + return nil + } + return i.Changes +} + +// GetComment returns the Comment field. +func (i *IssueCommentEvent) GetComment() *IssueComment { + if i == nil { + return nil + } + return i.Comment +} + +// GetInstallation returns the Installation field. +func (i *IssueCommentEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetIssue returns the Issue field. +func (i *IssueCommentEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetOrganization returns the Organization field. +func (i *IssueCommentEvent) GetOrganization() *Organization { + if i == nil { + return nil + } + return i.Organization +} + +// GetRepo returns the Repo field. +func (i *IssueCommentEvent) GetRepo() *Repository { + if i == nil { + return nil + } + return i.Repo +} + +// GetSender returns the Sender field. +func (i *IssueCommentEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetActor returns the Actor field. +func (i *IssueEvent) GetActor() *User { + if i == nil { + return nil + } + return i.Actor +} + +// GetAssignee returns the Assignee field. +func (i *IssueEvent) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetAssigner returns the Assigner field. +func (i *IssueEvent) GetAssigner() *User { + if i == nil { + return nil + } + return i.Assigner +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetCommitID() string { + if i == nil || i.CommitID == nil { + return "" + } + return *i.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetDismissedReview returns the DismissedReview field. +func (i *IssueEvent) GetDismissedReview() *DismissedReview { + if i == nil { + return nil + } + return i.DismissedReview +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetEvent() string { + if i == nil || i.Event == nil { + return "" + } + return *i.Event +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetID() int64 { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetIssue returns the Issue field. +func (i *IssueEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetLabel returns the Label field. +func (i *IssueEvent) GetLabel() *Label { + if i == nil { + return nil + } + return i.Label +} + +// GetLockReason returns the LockReason field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetLockReason() string { + if i == nil || i.LockReason == nil { + return "" + } + return *i.LockReason +} + +// GetMilestone returns the Milestone field. +func (i *IssueEvent) GetMilestone() *Milestone { + if i == nil { + return nil + } + return i.Milestone +} + +// GetProjectCard returns the ProjectCard field. +func (i *IssueEvent) GetProjectCard() *ProjectCard { + if i == nil { + return nil + } + return i.ProjectCard +} + +// GetRename returns the Rename field. +func (i *IssueEvent) GetRename() *Rename { + if i == nil { + return nil + } + return i.Rename +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (i *IssueEvent) GetRequestedReviewer() *User { + if i == nil { + return nil + } + return i.RequestedReviewer +} + +// GetReviewRequester returns the ReviewRequester field. +func (i *IssueEvent) GetReviewRequester() *User { + if i == nil { + return nil + } + return i.ReviewRequester +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueEvent) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetAssignee() string { + if i == nil || i.Assignee == nil { + return "" + } + return *i.Assignee +} + +// GetClosed returns the Closed field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetClosed() bool { + if i == nil || i.Closed == nil { + return false + } + return *i.Closed +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetClosedAt() time.Time { + if i == nil || i.ClosedAt == nil { + return time.Time{} + } + return *i.ClosedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetMilestone() int { + if i == nil || i.Milestone == nil { + return 0 + } + return *i.Milestone +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImport) GetUpdatedAt() time.Time { + if i == nil || i.UpdatedAt == nil { + return time.Time{} + } + return *i.UpdatedAt +} + +// GetCode returns the Code field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetCode() string { + if i == nil || i.Code == nil { + return "" + } + return *i.Code +} + +// GetField returns the Field field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetField() string { + if i == nil || i.Field == nil { + return "" + } + return *i.Field +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetLocation() string { + if i == nil || i.Location == nil { + return "" + } + return *i.Location +} + +// GetResource returns the Resource field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetResource() string { + if i == nil || i.Resource == nil { + return "" + } + return *i.Resource +} + +// GetValue returns the Value field if it's non-nil, zero value otherwise. +func (i *IssueImportError) GetValue() string { + if i == nil || i.Value == nil { + return "" + } + return *i.Value +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetCreatedAt() time.Time { + if i == nil || i.CreatedAt == nil { + return time.Time{} + } + return *i.CreatedAt +} + +// GetDocumentationURL returns the DocumentationURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetDocumentationURL() string { + if i == nil || i.DocumentationURL == nil { + return "" + } + return *i.DocumentationURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetID() int { + if i == nil || i.ID == nil { + return 0 + } + return *i.ID +} + +// GetImportIssuesURL returns the ImportIssuesURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetImportIssuesURL() string { + if i == nil || i.ImportIssuesURL == nil { + return "" + } + return *i.ImportIssuesURL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetMessage() string { + if i == nil || i.Message == nil { + return "" + } + return *i.Message +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetRepositoryURL() string { + if i == nil || i.RepositoryURL == nil { + return "" + } + return *i.RepositoryURL +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetStatus() string { + if i == nil || i.Status == nil { + return "" + } + return *i.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetUpdatedAt() time.Time { + if i == nil || i.UpdatedAt == nil { + return time.Time{} + } + return *i.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (i *IssueImportResponse) GetURL() string { + if i == nil || i.URL == nil { + return "" + } + return *i.URL +} + +// GetDirection returns the Direction field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetDirection() string { + if i == nil || i.Direction == nil { + return "" + } + return *i.Direction +} + +// GetSince returns the Since field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetSince() time.Time { + if i == nil || i.Since == nil { + return time.Time{} + } + return *i.Since +} + +// GetSort returns the Sort field if it's non-nil, zero value otherwise. +func (i *IssueListCommentsOptions) GetSort() string { + if i == nil || i.Sort == nil { + return "" + } + return *i.Sort +} + +// GetAssignee returns the Assignee field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetAssignee() string { + if i == nil || i.Assignee == nil { + return "" + } + return *i.Assignee +} + +// GetAssignees returns the Assignees field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetAssignees() []string { + if i == nil || i.Assignees == nil { + return nil + } + return *i.Assignees +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetBody() string { + if i == nil || i.Body == nil { + return "" + } + return *i.Body +} + +// GetLabels returns the Labels field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetLabels() []string { + if i == nil || i.Labels == nil { + return nil + } + return *i.Labels +} + +// GetMilestone returns the Milestone field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetMilestone() int { + if i == nil || i.Milestone == nil { + return 0 + } + return *i.Milestone +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetState() string { + if i == nil || i.State == nil { + return "" + } + return *i.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (i *IssueRequest) GetTitle() string { + if i == nil || i.Title == nil { + return "" + } + return *i.Title +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (i *IssuesEvent) GetAction() string { + if i == nil || i.Action == nil { + return "" + } + return *i.Action +} + +// GetAssignee returns the Assignee field. +func (i *IssuesEvent) GetAssignee() *User { + if i == nil { + return nil + } + return i.Assignee +} + +// GetChanges returns the Changes field. +func (i *IssuesEvent) GetChanges() *EditChange { + if i == nil { + return nil + } + return i.Changes +} + +// GetInstallation returns the Installation field. +func (i *IssuesEvent) GetInstallation() *Installation { + if i == nil { + return nil + } + return i.Installation +} + +// GetIssue returns the Issue field. +func (i *IssuesEvent) GetIssue() *Issue { + if i == nil { + return nil + } + return i.Issue +} + +// GetLabel returns the Label field. +func (i *IssuesEvent) GetLabel() *Label { + if i == nil { + return nil + } + return i.Label +} + +// GetRepo returns the Repo field. +func (i *IssuesEvent) GetRepo() *Repository { + if i == nil { + return nil + } + return i.Repo +} + +// GetSender returns the Sender field. +func (i *IssuesEvent) GetSender() *User { + if i == nil { + return nil + } + return i.Sender +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (i *IssuesSearchResult) GetIncompleteResults() bool { + if i == nil || i.IncompleteResults == nil { + return false + } + return *i.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (i *IssuesSearchResult) GetTotal() int { + if i == nil || i.Total == nil { + return 0 + } + return *i.Total +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetClosedIssues() int { + if i == nil || i.ClosedIssues == nil { + return 0 + } + return *i.ClosedIssues +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetOpenIssues() int { + if i == nil || i.OpenIssues == nil { + return 0 + } + return *i.OpenIssues +} + +// GetTotalIssues returns the TotalIssues field if it's non-nil, zero value otherwise. +func (i *IssueStats) GetTotalIssues() int { + if i == nil || i.TotalIssues == nil { + return 0 + } + return *i.TotalIssues +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (j *Jobs) GetTotalCount() int { + if j == nil || j.TotalCount == nil { + return 0 + } + return *j.TotalCount +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (k *Key) GetCreatedAt() Timestamp { + if k == nil || k.CreatedAt == nil { + return Timestamp{} + } + return *k.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (k *Key) GetID() int64 { + if k == nil || k.ID == nil { + return 0 + } + return *k.ID +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (k *Key) GetKey() string { + if k == nil || k.Key == nil { + return "" + } + return *k.Key +} + +// GetReadOnly returns the ReadOnly field if it's non-nil, zero value otherwise. +func (k *Key) GetReadOnly() bool { + if k == nil || k.ReadOnly == nil { + return false + } + return *k.ReadOnly +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (k *Key) GetTitle() string { + if k == nil || k.Title == nil { + return "" + } + return *k.Title +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (k *Key) GetURL() string { + if k == nil || k.URL == nil { + return "" + } + return *k.URL +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (k *Key) GetVerified() bool { + if k == nil || k.Verified == nil { + return false + } + return *k.Verified +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (l *Label) GetColor() string { + if l == nil || l.Color == nil { + return "" + } + return *l.Color +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (l *Label) GetDefault() bool { + if l == nil || l.Default == nil { + return false + } + return *l.Default +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *Label) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (l *Label) GetID() int64 { + if l == nil || l.ID == nil { + return 0 + } + return *l.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *Label) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (l *Label) GetNodeID() string { + if l == nil || l.NodeID == nil { + return "" + } + return *l.NodeID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *Label) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (l *LabelEvent) GetAction() string { + if l == nil || l.Action == nil { + return "" + } + return *l.Action +} + +// GetChanges returns the Changes field. +func (l *LabelEvent) GetChanges() *EditChange { + if l == nil { + return nil + } + return l.Changes +} + +// GetInstallation returns the Installation field. +func (l *LabelEvent) GetInstallation() *Installation { + if l == nil { + return nil + } + return l.Installation +} + +// GetLabel returns the Label field. +func (l *LabelEvent) GetLabel() *Label { + if l == nil { + return nil + } + return l.Label +} + +// GetOrg returns the Org field. +func (l *LabelEvent) GetOrg() *Organization { + if l == nil { + return nil + } + return l.Org +} + +// GetRepo returns the Repo field. +func (l *LabelEvent) GetRepo() *Repository { + if l == nil { + return nil + } + return l.Repo +} + +// GetColor returns the Color field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetColor() string { + if l == nil || l.Color == nil { + return "" + } + return *l.Color +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetDefault() bool { + if l == nil || l.Default == nil { + return false + } + return *l.Default +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetID() int64 { + if l == nil || l.ID == nil { + return 0 + } + return *l.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetScore returns the Score field. +func (l *LabelResult) GetScore() *float64 { + if l == nil { + return nil + } + return l.Score +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *LabelResult) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (l *LabelsSearchResult) GetIncompleteResults() bool { + if l == nil || l.IncompleteResults == nil { + return false + } + return *l.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *LabelsSearchResult) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetOID returns the OID field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetOID() string { + if l == nil || l.OID == nil { + return "" + } + return *l.OID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetPath() string { + if l == nil || l.Path == nil { + return "" + } + return *l.Path +} + +// GetRefName returns the RefName field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetRefName() string { + if l == nil || l.RefName == nil { + return "" + } + return *l.RefName +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (l *LargeFile) GetSize() int { + if l == nil || l.Size == nil { + return 0 + } + return *l.Size +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (l *License) GetBody() string { + if l == nil || l.Body == nil { + return "" + } + return *l.Body +} + +// GetConditions returns the Conditions field if it's non-nil, zero value otherwise. +func (l *License) GetConditions() []string { + if l == nil || l.Conditions == nil { + return nil + } + return *l.Conditions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (l *License) GetDescription() string { + if l == nil || l.Description == nil { + return "" + } + return *l.Description +} + +// GetFeatured returns the Featured field if it's non-nil, zero value otherwise. +func (l *License) GetFeatured() bool { + if l == nil || l.Featured == nil { + return false + } + return *l.Featured +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (l *License) GetHTMLURL() string { + if l == nil || l.HTMLURL == nil { + return "" + } + return *l.HTMLURL +} + +// GetImplementation returns the Implementation field if it's non-nil, zero value otherwise. +func (l *License) GetImplementation() string { + if l == nil || l.Implementation == nil { + return "" + } + return *l.Implementation +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (l *License) GetKey() string { + if l == nil || l.Key == nil { + return "" + } + return *l.Key +} + +// GetLimitations returns the Limitations field if it's non-nil, zero value otherwise. +func (l *License) GetLimitations() []string { + if l == nil || l.Limitations == nil { + return nil + } + return *l.Limitations +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (l *License) GetName() string { + if l == nil || l.Name == nil { + return "" + } + return *l.Name +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (l *License) GetPermissions() []string { + if l == nil || l.Permissions == nil { + return nil + } + return *l.Permissions +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (l *License) GetSPDXID() string { + if l == nil || l.SPDXID == nil { + return "" + } + return *l.SPDXID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (l *License) GetURL() string { + if l == nil || l.URL == nil { + return "" + } + return *l.URL +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetAppID() int64 { + if l == nil || l.AppID == nil { + return 0 + } + return *l.AppID +} + +// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetCheckName() string { + if l == nil || l.CheckName == nil { + return "" + } + return *l.CheckName +} + +// GetFilter returns the Filter field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetFilter() string { + if l == nil || l.Filter == nil { + return "" + } + return *l.Filter +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsOptions) GetStatus() string { + if l == nil || l.Status == nil { + return "" + } + return *l.Status +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *ListCheckRunsResults) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteOptions) GetAppID() int { + if l == nil || l.AppID == nil { + return 0 + } + return *l.AppID +} + +// GetCheckName returns the CheckName field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteOptions) GetCheckName() string { + if l == nil || l.CheckName == nil { + return "" + } + return *l.CheckName +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (l *ListCheckSuiteResults) GetTotal() int { + if l == nil || l.Total == nil { + return 0 + } + return *l.Total +} + +// GetAffiliation returns the Affiliation field if it's non-nil, zero value otherwise. +func (l *ListCollaboratorOptions) GetAffiliation() string { + if l == nil || l.Affiliation == nil { + return "" + } + return *l.Affiliation +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (l *ListExternalGroupsOptions) GetDisplayName() string { + if l == nil || l.DisplayName == nil { + return "" + } + return *l.DisplayName +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (l *ListRepositories) GetTotalCount() int { + if l == nil || l.TotalCount == nil { + return 0 + } + return *l.TotalCount +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetCount() int { + if l == nil || l.Count == nil { + return 0 + } + return *l.Count +} + +// GetFilter returns the Filter field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetFilter() string { + if l == nil || l.Filter == nil { + return "" + } + return *l.Filter +} + +// GetStartIndex returns the StartIndex field if it's non-nil, zero value otherwise. +func (l *ListSCIMProvisionedIdentitiesOptions) GetStartIndex() int { + if l == nil || l.StartIndex == nil { + return 0 + } + return *l.StartIndex +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (l *Location) GetEndColumn() int { + if l == nil || l.EndColumn == nil { + return 0 + } + return *l.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (l *Location) GetEndLine() int { + if l == nil || l.EndLine == nil { + return 0 + } + return *l.EndLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (l *Location) GetPath() string { + if l == nil || l.Path == nil { + return "" + } + return *l.Path +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (l *Location) GetStartColumn() int { + if l == nil || l.StartColumn == nil { + return 0 + } + return *l.StartColumn +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (l *Location) GetStartLine() int { + if l == nil || l.StartLine == nil { + return 0 + } + return *l.StartLine +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetEffectiveDate() Timestamp { + if m == nil || m.EffectiveDate == nil { + return Timestamp{} + } + return *m.EffectiveDate +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetPlan returns the Plan field. +func (m *MarketplacePendingChange) GetPlan() *MarketplacePlan { + if m == nil { + return nil + } + return m.Plan +} + +// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. +func (m *MarketplacePendingChange) GetUnitCount() int { + if m == nil || m.UnitCount == nil { + return 0 + } + return *m.UnitCount +} + +// GetAccountsURL returns the AccountsURL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetAccountsURL() string { + if m == nil || m.AccountsURL == nil { + return "" + } + return *m.AccountsURL +} + +// GetBullets returns the Bullets field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetBullets() []string { + if m == nil || m.Bullets == nil { + return nil + } + return *m.Bullets +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetDescription() string { + if m == nil || m.Description == nil { + return "" + } + return *m.Description +} + +// GetHasFreeTrial returns the HasFreeTrial field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetHasFreeTrial() bool { + if m == nil || m.HasFreeTrial == nil { + return false + } + return *m.HasFreeTrial +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetMonthlyPriceInCents returns the MonthlyPriceInCents field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetMonthlyPriceInCents() int { + if m == nil || m.MonthlyPriceInCents == nil { + return 0 + } + return *m.MonthlyPriceInCents +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetName() string { + if m == nil || m.Name == nil { + return "" + } + return *m.Name +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetNumber() int { + if m == nil || m.Number == nil { + return 0 + } + return *m.Number +} + +// GetPriceModel returns the PriceModel field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetPriceModel() string { + if m == nil || m.PriceModel == nil { + return "" + } + return *m.PriceModel +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetUnitName returns the UnitName field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetUnitName() string { + if m == nil || m.UnitName == nil { + return "" + } + return *m.UnitName +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetYearlyPriceInCents returns the YearlyPriceInCents field if it's non-nil, zero value otherwise. +func (m *MarketplacePlan) GetYearlyPriceInCents() int { + if m == nil || m.YearlyPriceInCents == nil { + return 0 + } + return *m.YearlyPriceInCents +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetLogin() string { + if m == nil || m.Login == nil { + return "" + } + return *m.Login +} + +// GetMarketplacePendingChange returns the MarketplacePendingChange field. +func (m *MarketplacePlanAccount) GetMarketplacePendingChange() *MarketplacePendingChange { + if m == nil { + return nil + } + return m.MarketplacePendingChange +} + +// GetMarketplacePurchase returns the MarketplacePurchase field. +func (m *MarketplacePlanAccount) GetMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.MarketplacePurchase +} + +// GetOrganizationBillingEmail returns the OrganizationBillingEmail field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetOrganizationBillingEmail() string { + if m == nil || m.OrganizationBillingEmail == nil { + return "" + } + return *m.OrganizationBillingEmail +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetType() string { + if m == nil || m.Type == nil { + return "" + } + return *m.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *MarketplacePlanAccount) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetBillingCycle returns the BillingCycle field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetBillingCycle() string { + if m == nil || m.BillingCycle == nil { + return "" + } + return *m.BillingCycle +} + +// GetFreeTrialEndsOn returns the FreeTrialEndsOn field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetFreeTrialEndsOn() Timestamp { + if m == nil || m.FreeTrialEndsOn == nil { + return Timestamp{} + } + return *m.FreeTrialEndsOn +} + +// GetNextBillingDate returns the NextBillingDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetNextBillingDate() Timestamp { + if m == nil || m.NextBillingDate == nil { + return Timestamp{} + } + return *m.NextBillingDate +} + +// GetOnFreeTrial returns the OnFreeTrial field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetOnFreeTrial() bool { + if m == nil || m.OnFreeTrial == nil { + return false + } + return *m.OnFreeTrial +} + +// GetPlan returns the Plan field. +func (m *MarketplacePurchase) GetPlan() *MarketplacePlan { + if m == nil { + return nil + } + return m.Plan +} + +// GetUnitCount returns the UnitCount field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetUnitCount() int { + if m == nil || m.UnitCount == nil { + return 0 + } + return *m.UnitCount +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchase) GetUpdatedAt() Timestamp { + if m == nil || m.UpdatedAt == nil { + return Timestamp{} + } + return *m.UpdatedAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetEffectiveDate returns the EffectiveDate field if it's non-nil, zero value otherwise. +func (m *MarketplacePurchaseEvent) GetEffectiveDate() Timestamp { + if m == nil || m.EffectiveDate == nil { + return Timestamp{} + } + return *m.EffectiveDate +} + +// GetInstallation returns the Installation field. +func (m *MarketplacePurchaseEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMarketplacePurchase returns the MarketplacePurchase field. +func (m *MarketplacePurchaseEvent) GetMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.MarketplacePurchase +} + +// GetPreviousMarketplacePurchase returns the PreviousMarketplacePurchase field. +func (m *MarketplacePurchaseEvent) GetPreviousMarketplacePurchase() *MarketplacePurchase { + if m == nil { + return nil + } + return m.PreviousMarketplacePurchase +} + +// GetSender returns the Sender field. +func (m *MarketplacePurchaseEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (m *Match) GetText() string { + if m == nil || m.Text == nil { + return "" + } + return *m.Text +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MemberEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetInstallation returns the Installation field. +func (m *MemberEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMember returns the Member field. +func (m *MemberEvent) GetMember() *User { + if m == nil { + return nil + } + return m.Member +} + +// GetRepo returns the Repo field. +func (m *MemberEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MemberEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetOrganization returns the Organization field. +func (m *Membership) GetOrganization() *Organization { + if m == nil { + return nil + } + return m.Organization +} + +// GetOrganizationURL returns the OrganizationURL field if it's non-nil, zero value otherwise. +func (m *Membership) GetOrganizationURL() string { + if m == nil || m.OrganizationURL == nil { + return "" + } + return *m.OrganizationURL +} + +// GetRole returns the Role field if it's non-nil, zero value otherwise. +func (m *Membership) GetRole() string { + if m == nil || m.Role == nil { + return "" + } + return *m.Role +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Membership) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Membership) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetUser returns the User field. +func (m *Membership) GetUser() *User { + if m == nil { + return nil + } + return m.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MembershipEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetInstallation returns the Installation field. +func (m *MembershipEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMember returns the Member field. +func (m *MembershipEvent) GetMember() *User { + if m == nil { + return nil + } + return m.Member +} + +// GetOrg returns the Org field. +func (m *MembershipEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetScope returns the Scope field if it's non-nil, zero value otherwise. +func (m *MembershipEvent) GetScope() string { + if m == nil || m.Scope == nil { + return "" + } + return *m.Scope +} + +// GetSender returns the Sender field. +func (m *MembershipEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetTeam returns the Team field. +func (m *MembershipEvent) GetTeam() *Team { + if m == nil { + return nil + } + return m.Team +} + +// GetText returns the Text field if it's non-nil, zero value otherwise. +func (m *Message) GetText() string { + if m == nil || m.Text == nil { + return "" + } + return *m.Text +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MetaEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetHook returns the Hook field. +func (m *MetaEvent) GetHook() *Hook { + if m == nil { + return nil + } + return m.Hook +} + +// GetHookID returns the HookID field if it's non-nil, zero value otherwise. +func (m *MetaEvent) GetHookID() int64 { + if m == nil || m.HookID == nil { + return 0 + } + return *m.HookID +} + +// GetInstallation returns the Installation field. +func (m *MetaEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *Metric) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (m *Metric) GetKey() string { + if m == nil || m.Key == nil { + return "" + } + return *m.Key +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (m *Metric) GetName() string { + if m == nil || m.Name == nil { + return "" + } + return *m.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *Metric) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetSPDXID returns the SPDXID field if it's non-nil, zero value otherwise. +func (m *Metric) GetSPDXID() string { + if m == nil || m.SPDXID == nil { + return "" + } + return *m.SPDXID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Metric) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (m *Migration) GetCreatedAt() string { + if m == nil || m.CreatedAt == nil { + return "" + } + return *m.CreatedAt +} + +// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. +func (m *Migration) GetExcludeAttachments() bool { + if m == nil || m.ExcludeAttachments == nil { + return false + } + return *m.ExcludeAttachments +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (m *Migration) GetGUID() string { + if m == nil || m.GUID == nil { + return "" + } + return *m.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *Migration) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. +func (m *Migration) GetLockRepositories() bool { + if m == nil || m.LockRepositories == nil { + return false + } + return *m.LockRepositories +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Migration) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *Migration) GetUpdatedAt() string { + if m == nil || m.UpdatedAt == nil { + return "" + } + return *m.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Migration) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetClosedAt() time.Time { + if m == nil || m.ClosedAt == nil { + return time.Time{} + } + return *m.ClosedAt +} + +// GetClosedIssues returns the ClosedIssues field if it's non-nil, zero value otherwise. +func (m *Milestone) GetClosedIssues() int { + if m == nil || m.ClosedIssues == nil { + return 0 + } + return *m.ClosedIssues +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetCreatedAt() time.Time { + if m == nil || m.CreatedAt == nil { + return time.Time{} + } + return *m.CreatedAt +} + +// GetCreator returns the Creator field. +func (m *Milestone) GetCreator() *User { + if m == nil { + return nil + } + return m.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (m *Milestone) GetDescription() string { + if m == nil || m.Description == nil { + return "" + } + return *m.Description +} + +// GetDueOn returns the DueOn field if it's non-nil, zero value otherwise. +func (m *Milestone) GetDueOn() time.Time { + if m == nil || m.DueOn == nil { + return time.Time{} + } + return *m.DueOn +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetHTMLURL() string { + if m == nil || m.HTMLURL == nil { + return "" + } + return *m.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (m *Milestone) GetID() int64 { + if m == nil || m.ID == nil { + return 0 + } + return *m.ID +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetLabelsURL() string { + if m == nil || m.LabelsURL == nil { + return "" + } + return *m.LabelsURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (m *Milestone) GetNodeID() string { + if m == nil || m.NodeID == nil { + return "" + } + return *m.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (m *Milestone) GetNumber() int { + if m == nil || m.Number == nil { + return 0 + } + return *m.Number +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (m *Milestone) GetOpenIssues() int { + if m == nil || m.OpenIssues == nil { + return 0 + } + return *m.OpenIssues +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *Milestone) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (m *Milestone) GetTitle() string { + if m == nil || m.Title == nil { + return "" + } + return *m.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (m *Milestone) GetUpdatedAt() time.Time { + if m == nil || m.UpdatedAt == nil { + return time.Time{} + } + return *m.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (m *Milestone) GetURL() string { + if m == nil || m.URL == nil { + return "" + } + return *m.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (m *MilestoneEvent) GetAction() string { + if m == nil || m.Action == nil { + return "" + } + return *m.Action +} + +// GetChanges returns the Changes field. +func (m *MilestoneEvent) GetChanges() *EditChange { + if m == nil { + return nil + } + return m.Changes +} + +// GetInstallation returns the Installation field. +func (m *MilestoneEvent) GetInstallation() *Installation { + if m == nil { + return nil + } + return m.Installation +} + +// GetMilestone returns the Milestone field. +func (m *MilestoneEvent) GetMilestone() *Milestone { + if m == nil { + return nil + } + return m.Milestone +} + +// GetOrg returns the Org field. +func (m *MilestoneEvent) GetOrg() *Organization { + if m == nil { + return nil + } + return m.Org +} + +// GetRepo returns the Repo field. +func (m *MilestoneEvent) GetRepo() *Repository { + if m == nil { + return nil + } + return m.Repo +} + +// GetSender returns the Sender field. +func (m *MilestoneEvent) GetSender() *User { + if m == nil { + return nil + } + return m.Sender +} + +// GetClosedMilestones returns the ClosedMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetClosedMilestones() int { + if m == nil || m.ClosedMilestones == nil { + return 0 + } + return *m.ClosedMilestones +} + +// GetOpenMilestones returns the OpenMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetOpenMilestones() int { + if m == nil || m.OpenMilestones == nil { + return 0 + } + return *m.OpenMilestones +} + +// GetTotalMilestones returns the TotalMilestones field if it's non-nil, zero value otherwise. +func (m *MilestoneStats) GetTotalMilestones() int { + if m == nil || m.TotalMilestones == nil { + return 0 + } + return *m.TotalMilestones +} + +// GetAnalysisKey returns the AnalysisKey field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetAnalysisKey() string { + if m == nil || m.AnalysisKey == nil { + return "" + } + return *m.AnalysisKey +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetCommitSHA() string { + if m == nil || m.CommitSHA == nil { + return "" + } + return *m.CommitSHA +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetEnvironment() string { + if m == nil || m.Environment == nil { + return "" + } + return *m.Environment +} + +// GetLocation returns the Location field. +func (m *MostRecentInstance) GetLocation() *Location { + if m == nil { + return nil + } + return m.Location +} + +// GetMessage returns the Message field. +func (m *MostRecentInstance) GetMessage() *Message { + if m == nil { + return nil + } + return m.Message +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetRef() string { + if m == nil || m.Ref == nil { + return "" + } + return *m.Ref +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (m *MostRecentInstance) GetState() string { + if m == nil || m.State == nil { + return "" + } + return *m.State +} + +// GetBase returns the Base field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetBase() string { + if n == nil || n.Base == nil { + return "" + } + return *n.Base +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetBody() string { + if n == nil || n.Body == nil { + return "" + } + return *n.Body +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetDraft() bool { + if n == nil || n.Draft == nil { + return false + } + return *n.Draft +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetHead() string { + if n == nil || n.Head == nil { + return "" + } + return *n.Head +} + +// GetIssue returns the Issue field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetIssue() int { + if n == nil || n.Issue == nil { + return 0 + } + return *n.Issue +} + +// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetMaintainerCanModify() bool { + if n == nil || n.MaintainerCanModify == nil { + return false + } + return *n.MaintainerCanModify +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (n *NewPullRequest) GetTitle() string { + if n == nil || n.Title == nil { + return "" + } + return *n.Title +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetDescription() string { + if n == nil || n.Description == nil { + return "" + } + return *n.Description +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetLDAPDN() string { + if n == nil || n.LDAPDN == nil { + return "" + } + return *n.LDAPDN +} + +// GetParentTeamID returns the ParentTeamID field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetParentTeamID() int64 { + if n == nil || n.ParentTeamID == nil { + return 0 + } + return *n.ParentTeamID +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPermission() string { + if n == nil || n.Permission == nil { + return "" + } + return *n.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (n *NewTeam) GetPrivacy() string { + if n == nil || n.Privacy == nil { + return "" + } + return *n.Privacy +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (n *Notification) GetID() string { + if n == nil || n.ID == nil { + return "" + } + return *n.ID +} + +// GetLastReadAt returns the LastReadAt field if it's non-nil, zero value otherwise. +func (n *Notification) GetLastReadAt() time.Time { + if n == nil || n.LastReadAt == nil { + return time.Time{} + } + return *n.LastReadAt +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (n *Notification) GetReason() string { + if n == nil || n.Reason == nil { + return "" + } + return *n.Reason +} + +// GetRepository returns the Repository field. +func (n *Notification) GetRepository() *Repository { + if n == nil { + return nil + } + return n.Repository +} + +// GetSubject returns the Subject field. +func (n *Notification) GetSubject() *NotificationSubject { + if n == nil { + return nil + } + return n.Subject +} + +// GetUnread returns the Unread field if it's non-nil, zero value otherwise. +func (n *Notification) GetUnread() bool { + if n == nil || n.Unread == nil { + return false + } + return *n.Unread +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (n *Notification) GetUpdatedAt() time.Time { + if n == nil || n.UpdatedAt == nil { + return time.Time{} + } + return *n.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (n *Notification) GetURL() string { + if n == nil || n.URL == nil { + return "" + } + return *n.URL +} + +// GetLatestCommentURL returns the LatestCommentURL field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetLatestCommentURL() string { + if n == nil || n.LatestCommentURL == nil { + return "" + } + return *n.LatestCommentURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetTitle() string { + if n == nil || n.Title == nil { + return "" + } + return *n.Title +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetType() string { + if n == nil || n.Type == nil { + return "" + } + return *n.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (n *NotificationSubject) GetURL() string { + if n == nil || n.URL == nil { + return "" + } + return *n.URL +} + +// GetClientID returns the ClientID field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetClientID() string { + if o == nil || o.ClientID == nil { + return "" + } + return *o.ClientID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (o *OAuthAPP) GetURL() string { + if o == nil || o.URL == nil { + return "" + } + return *o.URL +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetAvatarURL() string { + if o == nil || o.AvatarURL == nil { + return "" + } + return *o.AvatarURL +} + +// GetBillingEmail returns the BillingEmail field if it's non-nil, zero value otherwise. +func (o *Organization) GetBillingEmail() string { + if o == nil || o.BillingEmail == nil { + return "" + } + return *o.BillingEmail +} + +// GetBlog returns the Blog field if it's non-nil, zero value otherwise. +func (o *Organization) GetBlog() string { + if o == nil || o.Blog == nil { + return "" + } + return *o.Blog +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (o *Organization) GetCollaborators() int { + if o == nil || o.Collaborators == nil { + return 0 + } + return *o.Collaborators +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (o *Organization) GetCompany() string { + if o == nil || o.Company == nil { + return "" + } + return *o.Company +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (o *Organization) GetCreatedAt() time.Time { + if o == nil || o.CreatedAt == nil { + return time.Time{} + } + return *o.CreatedAt +} + +// GetDefaultRepoPermission returns the DefaultRepoPermission field if it's non-nil, zero value otherwise. +func (o *Organization) GetDefaultRepoPermission() string { + if o == nil || o.DefaultRepoPermission == nil { + return "" + } + return *o.DefaultRepoPermission +} + +// GetDefaultRepoSettings returns the DefaultRepoSettings field if it's non-nil, zero value otherwise. +func (o *Organization) GetDefaultRepoSettings() string { + if o == nil || o.DefaultRepoSettings == nil { + return "" + } + return *o.DefaultRepoSettings +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (o *Organization) GetDescription() string { + if o == nil || o.Description == nil { + return "" + } + return *o.Description +} + +// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. +func (o *Organization) GetDiskUsage() int { + if o == nil || o.DiskUsage == nil { + return 0 + } + return *o.DiskUsage +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (o *Organization) GetEmail() string { + if o == nil || o.Email == nil { + return "" + } + return *o.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetEventsURL() string { + if o == nil || o.EventsURL == nil { + return "" + } + return *o.EventsURL +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (o *Organization) GetFollowers() int { + if o == nil || o.Followers == nil { + return 0 + } + return *o.Followers +} + +// GetFollowing returns the Following field if it's non-nil, zero value otherwise. +func (o *Organization) GetFollowing() int { + if o == nil || o.Following == nil { + return 0 + } + return *o.Following +} + +// GetHasOrganizationProjects returns the HasOrganizationProjects field if it's non-nil, zero value otherwise. +func (o *Organization) GetHasOrganizationProjects() bool { + if o == nil || o.HasOrganizationProjects == nil { + return false + } + return *o.HasOrganizationProjects +} + +// GetHasRepositoryProjects returns the HasRepositoryProjects field if it's non-nil, zero value otherwise. +func (o *Organization) GetHasRepositoryProjects() bool { + if o == nil || o.HasRepositoryProjects == nil { + return false + } + return *o.HasRepositoryProjects +} + +// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetHooksURL() string { + if o == nil || o.HooksURL == nil { + return "" + } + return *o.HooksURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetHTMLURL() string { + if o == nil || o.HTMLURL == nil { + return "" + } + return *o.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (o *Organization) GetID() int64 { + if o == nil || o.ID == nil { + return 0 + } + return *o.ID +} + +// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetIssuesURL() string { + if o == nil || o.IssuesURL == nil { + return "" + } + return *o.IssuesURL +} + +// GetIsVerified returns the IsVerified field if it's non-nil, zero value otherwise. +func (o *Organization) GetIsVerified() bool { + if o == nil || o.IsVerified == nil { + return false + } + return *o.IsVerified +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (o *Organization) GetLocation() string { + if o == nil || o.Location == nil { + return "" + } + return *o.Location +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (o *Organization) GetLogin() string { + if o == nil || o.Login == nil { + return "" + } + return *o.Login +} + +// GetMembersAllowedRepositoryCreationType returns the MembersAllowedRepositoryCreationType field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersAllowedRepositoryCreationType() string { + if o == nil || o.MembersAllowedRepositoryCreationType == nil { + return "" + } + return *o.MembersAllowedRepositoryCreationType +} + +// GetMembersCanCreateInternalRepos returns the MembersCanCreateInternalRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreateInternalRepos() bool { + if o == nil || o.MembersCanCreateInternalRepos == nil { + return false + } + return *o.MembersCanCreateInternalRepos +} + +// GetMembersCanCreatePages returns the MembersCanCreatePages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePages() bool { + if o == nil || o.MembersCanCreatePages == nil { + return false + } + return *o.MembersCanCreatePages +} + +// GetMembersCanCreatePrivatePages returns the MembersCanCreatePrivatePages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePrivatePages() bool { + if o == nil || o.MembersCanCreatePrivatePages == nil { + return false + } + return *o.MembersCanCreatePrivatePages +} + +// GetMembersCanCreatePrivateRepos returns the MembersCanCreatePrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePrivateRepos() bool { + if o == nil || o.MembersCanCreatePrivateRepos == nil { + return false + } + return *o.MembersCanCreatePrivateRepos +} + +// GetMembersCanCreatePublicPages returns the MembersCanCreatePublicPages field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePublicPages() bool { + if o == nil || o.MembersCanCreatePublicPages == nil { + return false + } + return *o.MembersCanCreatePublicPages +} + +// GetMembersCanCreatePublicRepos returns the MembersCanCreatePublicRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreatePublicRepos() bool { + if o == nil || o.MembersCanCreatePublicRepos == nil { + return false + } + return *o.MembersCanCreatePublicRepos +} + +// GetMembersCanCreateRepos returns the MembersCanCreateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersCanCreateRepos() bool { + if o == nil || o.MembersCanCreateRepos == nil { + return false + } + return *o.MembersCanCreateRepos +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetMembersURL() string { + if o == nil || o.MembersURL == nil { + return "" + } + return *o.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (o *Organization) GetName() string { + if o == nil || o.Name == nil { + return "" + } + return *o.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (o *Organization) GetNodeID() string { + if o == nil || o.NodeID == nil { + return "" + } + return *o.NodeID +} + +// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetOwnedPrivateRepos() int { + if o == nil || o.OwnedPrivateRepos == nil { + return 0 + } + return *o.OwnedPrivateRepos +} + +// GetPlan returns the Plan field. +func (o *Organization) GetPlan() *Plan { + if o == nil { + return nil + } + return o.Plan +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (o *Organization) GetPrivateGists() int { + if o == nil || o.PrivateGists == nil { + return 0 + } + return *o.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicGists() int { + if o == nil || o.PublicGists == nil { + return 0 + } + return *o.PublicGists +} + +// GetPublicMembersURL returns the PublicMembersURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicMembersURL() string { + if o == nil || o.PublicMembersURL == nil { + return "" + } + return *o.PublicMembersURL +} + +// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetPublicRepos() int { + if o == nil || o.PublicRepos == nil { + return 0 + } + return *o.PublicRepos +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (o *Organization) GetReposURL() string { + if o == nil || o.ReposURL == nil { + return "" + } + return *o.ReposURL +} + +// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. +func (o *Organization) GetTotalPrivateRepos() int { + if o == nil || o.TotalPrivateRepos == nil { + return 0 + } + return *o.TotalPrivateRepos +} + +// GetTwitterUsername returns the TwitterUsername field if it's non-nil, zero value otherwise. +func (o *Organization) GetTwitterUsername() string { + if o == nil || o.TwitterUsername == nil { + return "" + } + return *o.TwitterUsername +} + +// GetTwoFactorRequirementEnabled returns the TwoFactorRequirementEnabled field if it's non-nil, zero value otherwise. +func (o *Organization) GetTwoFactorRequirementEnabled() bool { + if o == nil || o.TwoFactorRequirementEnabled == nil { + return false + } + return *o.TwoFactorRequirementEnabled +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (o *Organization) GetType() string { + if o == nil || o.Type == nil { + return "" + } + return *o.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (o *Organization) GetUpdatedAt() time.Time { + if o == nil || o.UpdatedAt == nil { + return time.Time{} + } + return *o.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (o *Organization) GetURL() string { + if o == nil || o.URL == nil { + return "" + } + return *o.URL +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrganizationCustomRepoRoles) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (o *OrganizationEvent) GetAction() string { + if o == nil || o.Action == nil { + return "" + } + return *o.Action +} + +// GetInstallation returns the Installation field. +func (o *OrganizationEvent) GetInstallation() *Installation { + if o == nil { + return nil + } + return o.Installation +} + +// GetInvitation returns the Invitation field. +func (o *OrganizationEvent) GetInvitation() *Invitation { + if o == nil { + return nil + } + return o.Invitation +} + +// GetMembership returns the Membership field. +func (o *OrganizationEvent) GetMembership() *Membership { + if o == nil { + return nil + } + return o.Membership +} + +// GetOrganization returns the Organization field. +func (o *OrganizationEvent) GetOrganization() *Organization { + if o == nil { + return nil + } + return o.Organization +} + +// GetSender returns the Sender field. +func (o *OrganizationEvent) GetSender() *User { + if o == nil { + return nil + } + return o.Sender +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (o *OrganizationInstallations) GetTotalCount() int { + if o == nil || o.TotalCount == nil { + return 0 + } + return *o.TotalCount +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (o *OrgBlockEvent) GetAction() string { + if o == nil || o.Action == nil { + return "" + } + return *o.Action +} + +// GetBlockedUser returns the BlockedUser field. +func (o *OrgBlockEvent) GetBlockedUser() *User { + if o == nil { + return nil + } + return o.BlockedUser +} + +// GetInstallation returns the Installation field. +func (o *OrgBlockEvent) GetInstallation() *Installation { + if o == nil { + return nil + } + return o.Installation +} + +// GetOrganization returns the Organization field. +func (o *OrgBlockEvent) GetOrganization() *Organization { + if o == nil { + return nil + } + return o.Organization +} + +// GetSender returns the Sender field. +func (o *OrgBlockEvent) GetSender() *User { + if o == nil { + return nil + } + return o.Sender +} + +// GetDisabledOrgs returns the DisabledOrgs field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetDisabledOrgs() int { + if o == nil || o.DisabledOrgs == nil { + return 0 + } + return *o.DisabledOrgs +} + +// GetTotalOrgs returns the TotalOrgs field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalOrgs() int { + if o == nil || o.TotalOrgs == nil { + return 0 + } + return *o.TotalOrgs +} + +// GetTotalTeamMembers returns the TotalTeamMembers field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalTeamMembers() int { + if o == nil || o.TotalTeamMembers == nil { + return 0 + } + return *o.TotalTeamMembers +} + +// GetTotalTeams returns the TotalTeams field if it's non-nil, zero value otherwise. +func (o *OrgStats) GetTotalTeams() int { + if o == nil || o.TotalTeams == nil { + return 0 + } + return *o.TotalTeams +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *Package) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Package) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *Package) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Package) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetOwner returns the Owner field. +func (p *Package) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *Package) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetPackageVersion returns the PackageVersion field. +func (p *Package) GetPackageVersion() *PackageVersion { + if p == nil { + return nil + } + return p.PackageVersion +} + +// GetRegistry returns the Registry field. +func (p *Package) GetRegistry() *PackageRegistry { + if p == nil { + return nil + } + return p.Registry +} + +// GetRepository returns the Repository field. +func (p *Package) GetRepository() *Repository { + if p == nil { + return nil + } + return p.Repository +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *Package) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Package) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVersionCount returns the VersionCount field if it's non-nil, zero value otherwise. +func (p *Package) GetVersionCount() int64 { + if p == nil || p.VersionCount == nil { + return 0 + } + return *p.VersionCount +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (p *Package) GetVisibility() string { + if p == nil || p.Visibility == nil { + return "" + } + return *p.Visibility +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PackageEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PackageEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *PackageEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetPackage returns the Package field. +func (p *PackageEvent) GetPackage() *Package { + if p == nil { + return nil + } + return p.Package +} + +// GetRepo returns the Repo field. +func (p *PackageEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PackageEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetAuthor returns the Author field. +func (p *PackageFile) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetContentType() string { + if p == nil || p.ContentType == nil { + return "" + } + return *p.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetDownloadURL() string { + if p == nil || p.DownloadURL == nil { + return "" + } + return *p.DownloadURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetMD5 returns the MD5 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetMD5() string { + if p == nil || p.MD5 == nil { + return "" + } + return *p.MD5 +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetSHA1 returns the SHA1 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSHA1() string { + if p == nil || p.SHA1 == nil { + return "" + } + return *p.SHA1 +} + +// GetSHA256 returns the SHA256 field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSHA256() string { + if p == nil || p.SHA256 == nil { + return "" + } + return *p.SHA256 +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetSize() int64 { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PackageFile) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (p *PackageListOptions) GetVisibility() string { + if p == nil || p.Visibility == nil { + return "" + } + return *p.Visibility +} + +// GetContainer returns the Container field. +func (p *PackageMetadata) GetContainer() *PackageContainerMetadata { + if p == nil { + return nil + } + return p.Container +} + +// GetPackageType returns the PackageType field if it's non-nil, zero value otherwise. +func (p *PackageMetadata) GetPackageType() string { + if p == nil || p.PackageType == nil { + return "" + } + return *p.PackageType +} + +// GetAboutURL returns the AboutURL field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetAboutURL() string { + if p == nil || p.AboutURL == nil { + return "" + } + return *p.AboutURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetType() string { + if p == nil || p.Type == nil { + return "" + } + return *p.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVendor returns the Vendor field if it's non-nil, zero value otherwise. +func (p *PackageRegistry) GetVendor() string { + if p == nil || p.Vendor == nil { + return "" + } + return *p.Vendor +} + +// GetAuthor returns the Author field. +func (p *PackageRelease) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetPrerelease() bool { + if p == nil || p.Prerelease == nil { + return false + } + return *p.Prerelease +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetPublishedAt() Timestamp { + if p == nil || p.PublishedAt == nil { + return Timestamp{} + } + return *p.PublishedAt +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetTagName() string { + if p == nil || p.TagName == nil { + return "" + } + return *p.TagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetTargetCommitish() string { + if p == nil || p.TargetCommitish == nil { + return "" + } + return *p.TargetCommitish +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageRelease) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAuthor returns the Author field. +func (p *PackageVersion) GetAuthor() *User { + if p == nil { + return nil + } + return p.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetBodyHTML() string { + if p == nil || p.BodyHTML == nil { + return "" + } + return *p.BodyHTML +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInstallationCommand returns the InstallationCommand field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetInstallationCommand() string { + if p == nil || p.InstallationCommand == nil { + return "" + } + return *p.InstallationCommand +} + +// GetManifest returns the Manifest field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetManifest() string { + if p == nil || p.Manifest == nil { + return "" + } + return *p.Manifest +} + +// GetMetadata returns the Metadata field. +func (p *PackageVersion) GetMetadata() *PackageMetadata { + if p == nil { + return nil + } + return p.Metadata +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPackageHTMLURL returns the PackageHTMLURL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetPackageHTMLURL() string { + if p == nil || p.PackageHTMLURL == nil { + return "" + } + return *p.PackageHTMLURL +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetPrerelease() bool { + if p == nil || p.Prerelease == nil { + return false + } + return *p.Prerelease +} + +// GetRelease returns the Release field. +func (p *PackageVersion) GetRelease() *PackageRelease { + if p == nil { + return nil + } + return p.Release +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetSummary() string { + if p == nil || p.Summary == nil { + return "" + } + return *p.Summary +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTagName() string { + if p == nil || p.TagName == nil { + return "" + } + return *p.TagName +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTargetCommitish() string { + if p == nil || p.TargetCommitish == nil { + return "" + } + return *p.TargetCommitish +} + +// GetTargetOID returns the TargetOID field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetTargetOID() string { + if p == nil || p.TargetOID == nil { + return "" + } + return *p.TargetOID +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (p *PackageVersion) GetVersion() string { + if p == nil || p.Version == nil { + return "" + } + return *p.Version +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *Page) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Page) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetPageName returns the PageName field if it's non-nil, zero value otherwise. +func (p *Page) GetPageName() string { + if p == nil || p.PageName == nil { + return "" + } + return *p.PageName +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *Page) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (p *Page) GetSummary() string { + if p == nil || p.Summary == nil { + return "" + } + return *p.Summary +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *Page) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetBuild returns the Build field. +func (p *PageBuildEvent) GetBuild() *PagesBuild { + if p == nil { + return nil + } + return p.Build +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PageBuildEvent) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInstallation returns the Installation field. +func (p *PageBuildEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetRepo returns the Repo field. +func (p *PageBuildEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PageBuildEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. +func (p *Pages) GetCNAME() string { + if p == nil || p.CNAME == nil { + return "" + } + return *p.CNAME +} + +// GetCustom404 returns the Custom404 field if it's non-nil, zero value otherwise. +func (p *Pages) GetCustom404() bool { + if p == nil || p.Custom404 == nil { + return false + } + return *p.Custom404 +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Pages) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetHTTPSCertificate returns the HTTPSCertificate field. +func (p *Pages) GetHTTPSCertificate() *PagesHTTPSCertificate { + if p == nil { + return nil + } + return p.HTTPSCertificate +} + +// GetHTTPSEnforced returns the HTTPSEnforced field if it's non-nil, zero value otherwise. +func (p *Pages) GetHTTPSEnforced() bool { + if p == nil || p.HTTPSEnforced == nil { + return false + } + return *p.HTTPSEnforced +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *Pages) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetSource returns the Source field. +func (p *Pages) GetSource() *PagesSource { + if p == nil { + return nil + } + return p.Source +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (p *Pages) GetStatus() string { + if p == nil || p.Status == nil { + return "" + } + return *p.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Pages) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetCommit returns the Commit field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetCommit() string { + if p == nil || p.Commit == nil { + return "" + } + return *p.Commit +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDuration returns the Duration field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetDuration() int { + if p == nil || p.Duration == nil { + return 0 + } + return *p.Duration +} + +// GetError returns the Error field. +func (p *PagesBuild) GetError() *PagesError { + if p == nil { + return nil + } + return p.Error +} + +// GetPusher returns the Pusher field. +func (p *PagesBuild) GetPusher() *User { + if p == nil { + return nil + } + return p.Pusher +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetStatus() string { + if p == nil || p.Status == nil { + return "" + } + return *p.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PagesBuild) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PagesError) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetExpiresAt() string { + if p == nil || p.ExpiresAt == nil { + return "" + } + return *p.ExpiresAt +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PagesHTTPSCertificate) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (p *PagesSource) GetBranch() string { + if p == nil || p.Branch == nil { + return "" + } + return *p.Branch +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (p *PagesSource) GetPath() string { + if p == nil || p.Path == nil { + return "" + } + return *p.Path +} + +// GetTotalPages returns the TotalPages field if it's non-nil, zero value otherwise. +func (p *PageStats) GetTotalPages() int { + if p == nil || p.TotalPages == nil { + return 0 + } + return *p.TotalPages +} + +// GetCNAME returns the CNAME field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetCNAME() string { + if p == nil || p.CNAME == nil { + return "" + } + return *p.CNAME +} + +// GetHTTPSEnforced returns the HTTPSEnforced field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetHTTPSEnforced() bool { + if p == nil || p.HTTPSEnforced == nil { + return false + } + return *p.HTTPSEnforced +} + +// GetPublic returns the Public field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetPublic() bool { + if p == nil || p.Public == nil { + return false + } + return *p.Public +} + +// GetSource returns the Source field if it's non-nil, zero value otherwise. +func (p *PagesUpdate) GetSource() string { + if p == nil || p.Source == nil { + return "" + } + return *p.Source +} + +// GetHook returns the Hook field. +func (p *PingEvent) GetHook() *Hook { + if p == nil { + return nil + } + return p.Hook +} + +// GetHookID returns the HookID field if it's non-nil, zero value otherwise. +func (p *PingEvent) GetHookID() int64 { + if p == nil || p.HookID == nil { + return 0 + } + return *p.HookID +} + +// GetInstallation returns the Installation field. +func (p *PingEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetZen returns the Zen field if it's non-nil, zero value otherwise. +func (p *PingEvent) GetZen() string { + if p == nil || p.Zen == nil { + return "" + } + return *p.Zen +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (p *Plan) GetCollaborators() int { + if p == nil || p.Collaborators == nil { + return 0 + } + return *p.Collaborators +} + +// GetFilledSeats returns the FilledSeats field if it's non-nil, zero value otherwise. +func (p *Plan) GetFilledSeats() int { + if p == nil || p.FilledSeats == nil { + return 0 + } + return *p.FilledSeats +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Plan) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetPrivateRepos returns the PrivateRepos field if it's non-nil, zero value otherwise. +func (p *Plan) GetPrivateRepos() int { + if p == nil || p.PrivateRepos == nil { + return 0 + } + return *p.PrivateRepos +} + +// GetSeats returns the Seats field if it's non-nil, zero value otherwise. +func (p *Plan) GetSeats() int { + if p == nil || p.Seats == nil { + return 0 + } + return *p.Seats +} + +// GetSpace returns the Space field if it's non-nil, zero value otherwise. +func (p *Plan) GetSpace() int { + if p == nil || p.Space == nil { + return 0 + } + return *p.Space +} + +// GetConfigURL returns the ConfigURL field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetConfigURL() string { + if p == nil || p.ConfigURL == nil { + return "" + } + return *p.ConfigURL +} + +// GetEnforcement returns the Enforcement field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetEnforcement() string { + if p == nil || p.Enforcement == nil { + return "" + } + return *p.Enforcement +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PreReceiveHook) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetHRef returns the HRef field if it's non-nil, zero value otherwise. +func (p *PRLink) GetHRef() string { + if p == nil || p.HRef == nil { + return "" + } + return *p.HRef +} + +// GetComments returns the Comments field. +func (p *PRLinks) GetComments() *PRLink { + if p == nil { + return nil + } + return p.Comments +} + +// GetCommits returns the Commits field. +func (p *PRLinks) GetCommits() *PRLink { + if p == nil { + return nil + } + return p.Commits +} + +// GetHTML returns the HTML field. +func (p *PRLinks) GetHTML() *PRLink { + if p == nil { + return nil + } + return p.HTML +} + +// GetIssue returns the Issue field. +func (p *PRLinks) GetIssue() *PRLink { + if p == nil { + return nil + } + return p.Issue +} + +// GetReviewComment returns the ReviewComment field. +func (p *PRLinks) GetReviewComment() *PRLink { + if p == nil { + return nil + } + return p.ReviewComment +} + +// GetReviewComments returns the ReviewComments field. +func (p *PRLinks) GetReviewComments() *PRLink { + if p == nil { + return nil + } + return p.ReviewComments +} + +// GetSelf returns the Self field. +func (p *PRLinks) GetSelf() *PRLink { + if p == nil { + return nil + } + return p.Self +} + +// GetStatuses returns the Statuses field. +func (p *PRLinks) GetStatuses() *PRLink { + if p == nil { + return nil + } + return p.Statuses +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *Project) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetColumnsURL returns the ColumnsURL field if it's non-nil, zero value otherwise. +func (p *Project) GetColumnsURL() string { + if p == nil || p.ColumnsURL == nil { + return "" + } + return *p.ColumnsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *Project) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetCreator returns the Creator field. +func (p *Project) GetCreator() *User { + if p == nil { + return nil + } + return p.Creator +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *Project) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *Project) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *Project) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *Project) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *Project) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganizationPermission returns the OrganizationPermission field if it's non-nil, zero value otherwise. +func (p *Project) GetOrganizationPermission() string { + if p == nil || p.OrganizationPermission == nil { + return "" + } + return *p.OrganizationPermission +} + +// GetOwnerURL returns the OwnerURL field if it's non-nil, zero value otherwise. +func (p *Project) GetOwnerURL() string { + if p == nil || p.OwnerURL == nil { + return "" + } + return *p.OwnerURL +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (p *Project) GetPrivate() bool { + if p == nil || p.Private == nil { + return false + } + return *p.Private +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *Project) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *Project) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *Project) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectBody) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetArchived() bool { + if p == nil || p.Archived == nil { + return false + } + return *p.Archived +} + +// GetColumnID returns the ColumnID field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetColumnID() int64 { + if p == nil || p.ColumnID == nil { + return 0 + } + return *p.ColumnID +} + +// GetColumnName returns the ColumnName field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetColumnName() string { + if p == nil || p.ColumnName == nil { + return "" + } + return *p.ColumnName +} + +// GetColumnURL returns the ColumnURL field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetColumnURL() string { + if p == nil || p.ColumnURL == nil { + return "" + } + return *p.ColumnURL +} + +// GetContentURL returns the ContentURL field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetContentURL() string { + if p == nil || p.ContentURL == nil { + return "" + } + return *p.ContentURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetCreator returns the Creator field. +func (p *ProjectCard) GetCreator() *User { + if p == nil { + return nil + } + return p.Creator +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetNote() string { + if p == nil || p.Note == nil { + return "" + } + return *p.Note +} + +// GetPreviousColumnName returns the PreviousColumnName field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetPreviousColumnName() string { + if p == nil || p.PreviousColumnName == nil { + return "" + } + return *p.PreviousColumnName +} + +// GetProjectID returns the ProjectID field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetProjectID() int64 { + if p == nil || p.ProjectID == nil { + return 0 + } + return *p.ProjectID +} + +// GetProjectURL returns the ProjectURL field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetProjectURL() string { + if p == nil || p.ProjectURL == nil { + return "" + } + return *p.ProjectURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *ProjectCard) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetNote returns the Note field. +func (p *ProjectCardChange) GetNote() *ProjectCardNote { + if p == nil { + return nil + } + return p.Note +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectCardEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfterID returns the AfterID field if it's non-nil, zero value otherwise. +func (p *ProjectCardEvent) GetAfterID() int64 { + if p == nil || p.AfterID == nil { + return 0 + } + return *p.AfterID +} + +// GetChanges returns the Changes field. +func (p *ProjectCardEvent) GetChanges() *ProjectCardChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *ProjectCardEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectCardEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProjectCard returns the ProjectCard field. +func (p *ProjectCardEvent) GetProjectCard() *ProjectCard { + if p == nil { + return nil + } + return p.ProjectCard +} + +// GetRepo returns the Repo field. +func (p *ProjectCardEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *ProjectCardEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetArchivedState returns the ArchivedState field if it's non-nil, zero value otherwise. +func (p *ProjectCardListOptions) GetArchivedState() string { + if p == nil || p.ArchivedState == nil { + return "" + } + return *p.ArchivedState +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectCardNote) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (p *ProjectCardOptions) GetArchived() bool { + if p == nil || p.Archived == nil { + return false + } + return *p.Archived +} + +// GetBody returns the Body field. +func (p *ProjectChange) GetBody() *ProjectBody { + if p == nil { + return nil + } + return p.Body +} + +// GetName returns the Name field. +func (p *ProjectChange) GetName() *ProjectName { + if p == nil { + return nil + } + return p.Name +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (p *ProjectCollaboratorOptions) GetPermission() string { + if p == nil || p.Permission == nil { + return "" + } + return *p.Permission +} + +// GetCardsURL returns the CardsURL field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetCardsURL() string { + if p == nil || p.CardsURL == nil { + return "" + } + return *p.CardsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetProjectURL returns the ProjectURL field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetProjectURL() string { + if p == nil || p.ProjectURL == nil { + return "" + } + return *p.ProjectURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *ProjectColumn) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetName returns the Name field. +func (p *ProjectColumnChange) GetName() *ProjectColumnName { + if p == nil { + return nil + } + return p.Name +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectColumnEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfterID returns the AfterID field if it's non-nil, zero value otherwise. +func (p *ProjectColumnEvent) GetAfterID() int64 { + if p == nil || p.AfterID == nil { + return 0 + } + return *p.AfterID +} + +// GetChanges returns the Changes field. +func (p *ProjectColumnEvent) GetChanges() *ProjectColumnChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *ProjectColumnEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectColumnEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProjectColumn returns the ProjectColumn field. +func (p *ProjectColumnEvent) GetProjectColumn() *ProjectColumn { + if p == nil { + return nil + } + return p.ProjectColumn +} + +// GetRepo returns the Repo field. +func (p *ProjectColumnEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *ProjectColumnEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectColumnName) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *ProjectEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *ProjectEvent) GetChanges() *ProjectChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *ProjectEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrg returns the Org field. +func (p *ProjectEvent) GetOrg() *Organization { + if p == nil { + return nil + } + return p.Org +} + +// GetProject returns the Project field. +func (p *ProjectEvent) GetProject() *Project { + if p == nil { + return nil + } + return p.Project +} + +// GetRepo returns the Repo field. +func (p *ProjectEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *ProjectEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (p *ProjectName) GetFrom() string { + if p == nil || p.From == nil { + return "" + } + return *p.From +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *ProjectOptions) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *ProjectOptions) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetOrganizationPermission returns the OrganizationPermission field if it's non-nil, zero value otherwise. +func (p *ProjectOptions) GetOrganizationPermission() string { + if p == nil || p.OrganizationPermission == nil { + return "" + } + return *p.OrganizationPermission +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (p *ProjectOptions) GetPrivate() bool { + if p == nil || p.Private == nil { + return false + } + return *p.Private +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *ProjectOptions) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (p *ProjectPermissionLevel) GetPermission() string { + if p == nil || p.Permission == nil { + return "" + } + return *p.Permission +} + +// GetUser returns the User field. +func (p *ProjectPermissionLevel) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAllowDeletions returns the AllowDeletions field. +func (p *Protection) GetAllowDeletions() *AllowDeletions { + if p == nil { + return nil + } + return p.AllowDeletions +} + +// GetAllowForcePushes returns the AllowForcePushes field. +func (p *Protection) GetAllowForcePushes() *AllowForcePushes { + if p == nil { + return nil + } + return p.AllowForcePushes +} + +// GetEnforceAdmins returns the EnforceAdmins field. +func (p *Protection) GetEnforceAdmins() *AdminEnforcement { + if p == nil { + return nil + } + return p.EnforceAdmins +} + +// GetRequiredConversationResolution returns the RequiredConversationResolution field. +func (p *Protection) GetRequiredConversationResolution() *RequiredConversationResolution { + if p == nil { + return nil + } + return p.RequiredConversationResolution +} + +// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. +func (p *Protection) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcement { + if p == nil { + return nil + } + return p.RequiredPullRequestReviews +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *Protection) GetRequiredStatusChecks() *RequiredStatusChecks { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRequireLinearHistory returns the RequireLinearHistory field. +func (p *Protection) GetRequireLinearHistory() *RequireLinearHistory { + if p == nil { + return nil + } + return p.RequireLinearHistory +} + +// GetRestrictions returns the Restrictions field. +func (p *Protection) GetRestrictions() *BranchRestrictions { + if p == nil { + return nil + } + return p.Restrictions +} + +// GetAuthorizedActorNames returns the AuthorizedActorNames field. +func (p *ProtectionChanges) GetAuthorizedActorNames() *AuthorizedActorNames { + if p == nil { + return nil + } + return p.AuthorizedActorNames +} + +// GetAuthorizedActorsOnly returns the AuthorizedActorsOnly field. +func (p *ProtectionChanges) GetAuthorizedActorsOnly() *AuthorizedActorsOnly { + if p == nil { + return nil + } + return p.AuthorizedActorsOnly +} + +// GetAllowDeletions returns the AllowDeletions field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetAllowDeletions() bool { + if p == nil || p.AllowDeletions == nil { + return false + } + return *p.AllowDeletions +} + +// GetAllowForcePushes returns the AllowForcePushes field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetAllowForcePushes() bool { + if p == nil || p.AllowForcePushes == nil { + return false + } + return *p.AllowForcePushes +} + +// GetRequiredConversationResolution returns the RequiredConversationResolution field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetRequiredConversationResolution() bool { + if p == nil || p.RequiredConversationResolution == nil { + return false + } + return *p.RequiredConversationResolution +} + +// GetRequiredPullRequestReviews returns the RequiredPullRequestReviews field. +func (p *ProtectionRequest) GetRequiredPullRequestReviews() *PullRequestReviewsEnforcementRequest { + if p == nil { + return nil + } + return p.RequiredPullRequestReviews +} + +// GetRequiredStatusChecks returns the RequiredStatusChecks field. +func (p *ProtectionRequest) GetRequiredStatusChecks() *RequiredStatusChecks { + if p == nil { + return nil + } + return p.RequiredStatusChecks +} + +// GetRequireLinearHistory returns the RequireLinearHistory field if it's non-nil, zero value otherwise. +func (p *ProtectionRequest) GetRequireLinearHistory() bool { + if p == nil || p.RequireLinearHistory == nil { + return false + } + return *p.RequireLinearHistory +} + +// GetRestrictions returns the Restrictions field. +func (p *ProtectionRequest) GetRestrictions() *BranchRestrictionsRequest { + if p == nil { + return nil + } + return p.Restrictions +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetType() string { + if p == nil || p.Type == nil { + return "" + } + return *p.Type +} + +// GetWaitTimer returns the WaitTimer field if it's non-nil, zero value otherwise. +func (p *ProtectionRule) GetWaitTimer() int { + if p == nil || p.WaitTimer == nil { + return 0 + } + return *p.WaitTimer +} + +// GetInstallation returns the Installation field. +func (p *PublicEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetRepo returns the Repo field. +func (p *PublicEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PublicEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetKey returns the Key field if it's non-nil, zero value otherwise. +func (p *PublicKey) GetKey() string { + if p == nil || p.Key == nil { + return "" + } + return *p.Key +} + +// GetKeyID returns the KeyID field if it's non-nil, zero value otherwise. +func (p *PublicKey) GetKeyID() string { + if p == nil || p.KeyID == nil { + return "" + } + return *p.KeyID +} + +// GetActiveLockReason returns the ActiveLockReason field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetActiveLockReason() string { + if p == nil || p.ActiveLockReason == nil { + return "" + } + return *p.ActiveLockReason +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetAdditions() int { + if p == nil || p.Additions == nil { + return 0 + } + return *p.Additions +} + +// GetAssignee returns the Assignee field. +func (p *PullRequest) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetAutoMerge returns the AutoMerge field. +func (p *PullRequest) GetAutoMerge() *PullRequestAutoMerge { + if p == nil { + return nil + } + return p.AutoMerge +} + +// GetBase returns the Base field. +func (p *PullRequest) GetBase() *PullRequestBranch { + if p == nil { + return nil + } + return p.Base +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetChangedFiles returns the ChangedFiles field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetChangedFiles() int { + if p == nil || p.ChangedFiles == nil { + return 0 + } + return *p.ChangedFiles +} + +// GetClosedAt returns the ClosedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetClosedAt() time.Time { + if p == nil || p.ClosedAt == nil { + return time.Time{} + } + return *p.ClosedAt +} + +// GetComments returns the Comments field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetComments() int { + if p == nil || p.Comments == nil { + return 0 + } + return *p.Comments +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommentsURL() string { + if p == nil || p.CommentsURL == nil { + return "" + } + return *p.CommentsURL +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommits() int { + if p == nil || p.Commits == nil { + return 0 + } + return *p.Commits +} + +// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCommitsURL() string { + if p == nil || p.CommitsURL == nil { + return "" + } + return *p.CommitsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetCreatedAt() time.Time { + if p == nil || p.CreatedAt == nil { + return time.Time{} + } + return *p.CreatedAt +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDeletions() int { + if p == nil || p.Deletions == nil { + return 0 + } + return *p.Deletions +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDiffURL() string { + if p == nil || p.DiffURL == nil { + return "" + } + return *p.DiffURL +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetDraft() bool { + if p == nil || p.Draft == nil { + return false + } + return *p.Draft +} + +// GetHead returns the Head field. +func (p *PullRequest) GetHead() *PullRequestBranch { + if p == nil { + return nil + } + return p.Head +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetIssueURL returns the IssueURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetIssueURL() string { + if p == nil || p.IssueURL == nil { + return "" + } + return *p.IssueURL +} + +// GetLinks returns the Links field. +func (p *PullRequest) GetLinks() *PRLinks { + if p == nil { + return nil + } + return p.Links +} + +// GetLocked returns the Locked field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetLocked() bool { + if p == nil || p.Locked == nil { + return false + } + return *p.Locked +} + +// GetMaintainerCanModify returns the MaintainerCanModify field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMaintainerCanModify() bool { + if p == nil || p.MaintainerCanModify == nil { + return false + } + return *p.MaintainerCanModify +} + +// GetMergeable returns the Mergeable field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeable() bool { + if p == nil || p.Mergeable == nil { + return false + } + return *p.Mergeable +} + +// GetMergeableState returns the MergeableState field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeableState() string { + if p == nil || p.MergeableState == nil { + return "" + } + return *p.MergeableState +} + +// GetMergeCommitSHA returns the MergeCommitSHA field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergeCommitSHA() string { + if p == nil || p.MergeCommitSHA == nil { + return "" + } + return *p.MergeCommitSHA +} + +// GetMerged returns the Merged field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMerged() bool { + if p == nil || p.Merged == nil { + return false + } + return *p.Merged +} + +// GetMergedAt returns the MergedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetMergedAt() time.Time { + if p == nil || p.MergedAt == nil { + return time.Time{} + } + return *p.MergedAt +} + +// GetMergedBy returns the MergedBy field. +func (p *PullRequest) GetMergedBy() *User { + if p == nil { + return nil + } + return p.MergedBy +} + +// GetMilestone returns the Milestone field. +func (p *PullRequest) GetMilestone() *Milestone { + if p == nil { + return nil + } + return p.Milestone +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetPatchURL() string { + if p == nil || p.PatchURL == nil { + return "" + } + return *p.PatchURL +} + +// GetRebaseable returns the Rebaseable field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetRebaseable() bool { + if p == nil || p.Rebaseable == nil { + return false + } + return *p.Rebaseable +} + +// GetReviewComments returns the ReviewComments field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewComments() int { + if p == nil || p.ReviewComments == nil { + return 0 + } + return *p.ReviewComments +} + +// GetReviewCommentsURL returns the ReviewCommentsURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewCommentsURL() string { + if p == nil || p.ReviewCommentsURL == nil { + return "" + } + return *p.ReviewCommentsURL +} + +// GetReviewCommentURL returns the ReviewCommentURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetReviewCommentURL() string { + if p == nil || p.ReviewCommentURL == nil { + return "" + } + return *p.ReviewCommentURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetStatusesURL() string { + if p == nil || p.StatusesURL == nil { + return "" + } + return *p.StatusesURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetTitle() string { + if p == nil || p.Title == nil { + return "" + } + return *p.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetUpdatedAt() time.Time { + if p == nil || p.UpdatedAt == nil { + return time.Time{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequest) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetUser returns the User field. +func (p *PullRequest) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetCommitMessage() string { + if p == nil || p.CommitMessage == nil { + return "" + } + return *p.CommitMessage +} + +// GetCommitTitle returns the CommitTitle field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetCommitTitle() string { + if p == nil || p.CommitTitle == nil { + return "" + } + return *p.CommitTitle +} + +// GetEnabledBy returns the EnabledBy field. +func (p *PullRequestAutoMerge) GetEnabledBy() *User { + if p == nil { + return nil + } + return p.EnabledBy +} + +// GetMergeMethod returns the MergeMethod field if it's non-nil, zero value otherwise. +func (p *PullRequestAutoMerge) GetMergeMethod() string { + if p == nil || p.MergeMethod == nil { + return "" + } + return *p.MergeMethod +} + +// GetLabel returns the Label field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetLabel() string { + if p == nil || p.Label == nil { + return "" + } + return *p.Label +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetRef() string { + if p == nil || p.Ref == nil { + return "" + } + return *p.Ref +} + +// GetRepo returns the Repo field. +func (p *PullRequestBranch) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PullRequestBranch) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetUser returns the User field. +func (p *PullRequestBranch) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetExpectedHeadSHA returns the ExpectedHeadSHA field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateOptions) GetExpectedHeadSHA() string { + if p == nil || p.ExpectedHeadSHA == nil { + return "" + } + return *p.ExpectedHeadSHA +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateResponse) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestBranchUpdateResponse) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetCreatedAt() time.Time { + if p == nil || p.CreatedAt == nil { + return time.Time{} + } + return *p.CreatedAt +} + +// GetDiffHunk returns the DiffHunk field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetDiffHunk() string { + if p == nil || p.DiffHunk == nil { + return "" + } + return *p.DiffHunk +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetInReplyTo returns the InReplyTo field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetInReplyTo() int64 { + if p == nil || p.InReplyTo == nil { + return 0 + } + return *p.InReplyTo +} + +// GetLine returns the Line field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetLine() int { + if p == nil || p.Line == nil { + return 0 + } + return *p.Line +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetOriginalCommitID returns the OriginalCommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalCommitID() string { + if p == nil || p.OriginalCommitID == nil { + return "" + } + return *p.OriginalCommitID +} + +// GetOriginalLine returns the OriginalLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalLine() int { + if p == nil || p.OriginalLine == nil { + return 0 + } + return *p.OriginalLine +} + +// GetOriginalPosition returns the OriginalPosition field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalPosition() int { + if p == nil || p.OriginalPosition == nil { + return 0 + } + return *p.OriginalPosition +} + +// GetOriginalStartLine returns the OriginalStartLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetOriginalStartLine() int { + if p == nil || p.OriginalStartLine == nil { + return 0 + } + return *p.OriginalStartLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPath() string { + if p == nil || p.Path == nil { + return "" + } + return *p.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPosition() int { + if p == nil || p.Position == nil { + return 0 + } + return *p.Position +} + +// GetPullRequestReviewID returns the PullRequestReviewID field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPullRequestReviewID() int64 { + if p == nil || p.PullRequestReviewID == nil { + return 0 + } + return *p.PullRequestReviewID +} + +// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetPullRequestURL() string { + if p == nil || p.PullRequestURL == nil { + return "" + } + return *p.PullRequestURL +} + +// GetReactions returns the Reactions field. +func (p *PullRequestComment) GetReactions() *Reactions { + if p == nil { + return nil + } + return p.Reactions +} + +// GetSide returns the Side field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetSide() string { + if p == nil || p.Side == nil { + return "" + } + return *p.Side +} + +// GetStartLine returns the StartLine field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetStartLine() int { + if p == nil || p.StartLine == nil { + return 0 + } + return *p.StartLine +} + +// GetStartSide returns the StartSide field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetStartSide() string { + if p == nil || p.StartSide == nil { + return "" + } + return *p.StartSide +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetUpdatedAt() time.Time { + if p == nil || p.UpdatedAt == nil { + return time.Time{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestComment) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetUser returns the User field. +func (p *PullRequestComment) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetAssignee returns the Assignee field. +func (p *PullRequestEvent) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetChanges returns the Changes field. +func (p *PullRequestEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *PullRequestEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetLabel returns the Label field. +func (p *PullRequestEvent) GetLabel() *Label { + if p == nil { + return nil + } + return p.Label +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequestEvent) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganization returns the Organization field. +func (p *PullRequestEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (p *PullRequestEvent) GetRequestedReviewer() *User { + if p == nil { + return nil + } + return p.RequestedReviewer +} + +// GetRequestedTeam returns the RequestedTeam field. +func (p *PullRequestEvent) GetRequestedTeam() *Team { + if p == nil { + return nil + } + return p.RequestedTeam +} + +// GetSender returns the Sender field. +func (p *PullRequestEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetDiffURL returns the DiffURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetDiffURL() string { + if p == nil || p.DiffURL == nil { + return "" + } + return *p.DiffURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetPatchURL returns the PatchURL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetPatchURL() string { + if p == nil || p.PatchURL == nil { + return "" + } + return *p.PatchURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PullRequestLinks) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetMerged returns the Merged field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetMerged() bool { + if p == nil || p.Merged == nil { + return false + } + return *p.Merged +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (p *PullRequestMergeResult) GetSHA() string { + if p == nil || p.SHA == nil { + return "" + } + return *p.SHA +} + +// GetAuthorAssociation returns the AuthorAssociation field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetAuthorAssociation() string { + if p == nil || p.AuthorAssociation == nil { + return "" + } + return *p.AuthorAssociation +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetPullRequestURL returns the PullRequestURL field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetPullRequestURL() string { + if p == nil || p.PullRequestURL == nil { + return "" + } + return *p.PullRequestURL +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetState() string { + if p == nil || p.State == nil { + return "" + } + return *p.State +} + +// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. +func (p *PullRequestReview) GetSubmittedAt() time.Time { + if p == nil || p.SubmittedAt == nil { + return time.Time{} + } + return *p.SubmittedAt +} + +// GetUser returns the User field. +func (p *PullRequestReview) GetUser() *User { + if p == nil { + return nil + } + return p.User +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewCommentEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetChanges returns the Changes field. +func (p *PullRequestReviewCommentEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetComment returns the Comment field. +func (p *PullRequestReviewCommentEvent) GetComment() *PullRequestComment { + if p == nil { + return nil + } + return p.Comment +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewCommentEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewCommentEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewCommentEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewCommentEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewDismissalRequest) GetMessage() string { + if p == nil || p.Message == nil { + return "" + } + return *p.Message +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrganization returns the Organization field. +func (p *PullRequestReviewEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetReview returns the Review field. +func (p *PullRequestReviewEvent) GetReview() *PullRequestReview { + if p == nil { + return nil + } + return p.Review +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetBody() string { + if p == nil || p.Body == nil { + return "" + } + return *p.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetCommitID() string { + if p == nil || p.CommitID == nil { + return "" + } + return *p.CommitID +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetEvent() string { + if p == nil || p.Event == nil { + return "" + } + return *p.Event +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewRequest) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetDismissalRestrictions returns the DismissalRestrictions field. +func (p *PullRequestReviewsEnforcement) GetDismissalRestrictions() *DismissalRestrictions { + if p == nil { + return nil + } + return p.DismissalRestrictions +} + +// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. +func (p *PullRequestReviewsEnforcementRequest) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { + if p == nil { + return nil + } + return p.DismissalRestrictionsRequest +} + +// GetDismissalRestrictionsRequest returns the DismissalRestrictionsRequest field. +func (p *PullRequestReviewsEnforcementUpdate) GetDismissalRestrictionsRequest() *DismissalRestrictionsRequest { + if p == nil { + return nil + } + return p.DismissalRestrictionsRequest +} + +// GetDismissStaleReviews returns the DismissStaleReviews field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetDismissStaleReviews() bool { + if p == nil || p.DismissStaleReviews == nil { + return false + } + return *p.DismissStaleReviews +} + +// GetRequireCodeOwnerReviews returns the RequireCodeOwnerReviews field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewsEnforcementUpdate) GetRequireCodeOwnerReviews() bool { + if p == nil || p.RequireCodeOwnerReviews == nil { + return false + } + return *p.RequireCodeOwnerReviews +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestReviewThreadEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetInstallation returns the Installation field. +func (p *PullRequestReviewThreadEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestReviewThreadEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestReviewThreadEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PullRequestReviewThreadEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetThread returns the Thread field. +func (p *PullRequestReviewThreadEvent) GetThread() *PullRequestThread { + if p == nil { + return nil + } + return p.Thread +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetAssignee returns the Assignee field. +func (p *PullRequestTargetEvent) GetAssignee() *User { + if p == nil { + return nil + } + return p.Assignee +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetChanges returns the Changes field. +func (p *PullRequestTargetEvent) GetChanges() *EditChange { + if p == nil { + return nil + } + return p.Changes +} + +// GetInstallation returns the Installation field. +func (p *PullRequestTargetEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetLabel returns the Label field. +func (p *PullRequestTargetEvent) GetLabel() *Label { + if p == nil { + return nil + } + return p.Label +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (p *PullRequestTargetEvent) GetNumber() int { + if p == nil || p.Number == nil { + return 0 + } + return *p.Number +} + +// GetOrganization returns the Organization field. +func (p *PullRequestTargetEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPullRequest returns the PullRequest field. +func (p *PullRequestTargetEvent) GetPullRequest() *PullRequest { + if p == nil { + return nil + } + return p.PullRequest +} + +// GetRepo returns the Repo field. +func (p *PullRequestTargetEvent) GetRepo() *Repository { + if p == nil { + return nil + } + return p.Repo +} + +// GetRequestedReviewer returns the RequestedReviewer field. +func (p *PullRequestTargetEvent) GetRequestedReviewer() *User { + if p == nil { + return nil + } + return p.RequestedReviewer +} + +// GetRequestedTeam returns the RequestedTeam field. +func (p *PullRequestTargetEvent) GetRequestedTeam() *Team { + if p == nil { + return nil + } + return p.RequestedTeam +} + +// GetSender returns the Sender field. +func (p *PullRequestTargetEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PullRequestThread) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PullRequestThread) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetMergablePulls returns the MergablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergablePulls() int { + if p == nil || p.MergablePulls == nil { + return 0 + } + return *p.MergablePulls +} + +// GetMergedPulls returns the MergedPulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetMergedPulls() int { + if p == nil || p.MergedPulls == nil { + return 0 + } + return *p.MergedPulls +} + +// GetTotalPulls returns the TotalPulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetTotalPulls() int { + if p == nil || p.TotalPulls == nil { + return 0 + } + return *p.TotalPulls +} + +// GetUnmergablePulls returns the UnmergablePulls field if it's non-nil, zero value otherwise. +func (p *PullStats) GetUnmergablePulls() int { + if p == nil || p.UnmergablePulls == nil { + return 0 + } + return *p.UnmergablePulls +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetCommits() int { + if p == nil || p.Commits == nil { + return 0 + } + return *p.Commits +} + +// GetDay returns the Day field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetDay() int { + if p == nil || p.Day == nil { + return 0 + } + return *p.Day +} + +// GetHour returns the Hour field if it's non-nil, zero value otherwise. +func (p *PunchCard) GetHour() int { + if p == nil || p.Hour == nil { + return 0 + } + return *p.Hour +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetAction() string { + if p == nil || p.Action == nil { + return "" + } + return *p.Action +} + +// GetAfter returns the After field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetAfter() string { + if p == nil || p.After == nil { + return "" + } + return *p.After +} + +// GetBaseRef returns the BaseRef field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetBaseRef() string { + if p == nil || p.BaseRef == nil { + return "" + } + return *p.BaseRef +} + +// GetBefore returns the Before field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetBefore() string { + if p == nil || p.Before == nil { + return "" + } + return *p.Before +} + +// GetCompare returns the Compare field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetCompare() string { + if p == nil || p.Compare == nil { + return "" + } + return *p.Compare +} + +// GetCreated returns the Created field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetCreated() bool { + if p == nil || p.Created == nil { + return false + } + return *p.Created +} + +// GetDeleted returns the Deleted field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetDeleted() bool { + if p == nil || p.Deleted == nil { + return false + } + return *p.Deleted +} + +// GetDistinctSize returns the DistinctSize field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetDistinctSize() int { + if p == nil || p.DistinctSize == nil { + return 0 + } + return *p.DistinctSize +} + +// GetForced returns the Forced field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetForced() bool { + if p == nil || p.Forced == nil { + return false + } + return *p.Forced +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetHead() string { + if p == nil || p.Head == nil { + return "" + } + return *p.Head +} + +// GetHeadCommit returns the HeadCommit field. +func (p *PushEvent) GetHeadCommit() *HeadCommit { + if p == nil { + return nil + } + return p.HeadCommit +} + +// GetInstallation returns the Installation field. +func (p *PushEvent) GetInstallation() *Installation { + if p == nil { + return nil + } + return p.Installation +} + +// GetOrganization returns the Organization field. +func (p *PushEvent) GetOrganization() *Organization { + if p == nil { + return nil + } + return p.Organization +} + +// GetPusher returns the Pusher field. +func (p *PushEvent) GetPusher() *User { + if p == nil { + return nil + } + return p.Pusher +} + +// GetPushID returns the PushID field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetPushID() int64 { + if p == nil || p.PushID == nil { + return 0 + } + return *p.PushID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetRef() string { + if p == nil || p.Ref == nil { + return "" + } + return *p.Ref +} + +// GetRepo returns the Repo field. +func (p *PushEvent) GetRepo() *PushEventRepository { + if p == nil { + return nil + } + return p.Repo +} + +// GetSender returns the Sender field. +func (p *PushEvent) GetSender() *User { + if p == nil { + return nil + } + return p.Sender +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PushEvent) GetSize() int { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (p *PushEventRepoOwner) GetEmail() string { + if p == nil || p.Email == nil { + return "" + } + return *p.Email +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PushEventRepoOwner) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetArchived() bool { + if p == nil || p.Archived == nil { + return false + } + return *p.Archived +} + +// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetArchiveURL() string { + if p == nil || p.ArchiveURL == nil { + return "" + } + return *p.ArchiveURL +} + +// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetCloneURL() string { + if p == nil || p.CloneURL == nil { + return "" + } + return *p.CloneURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetCreatedAt() Timestamp { + if p == nil || p.CreatedAt == nil { + return Timestamp{} + } + return *p.CreatedAt +} + +// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDefaultBranch() string { + if p == nil || p.DefaultBranch == nil { + return "" + } + return *p.DefaultBranch +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDescription() string { + if p == nil || p.Description == nil { + return "" + } + return *p.Description +} + +// GetDisabled returns the Disabled field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetDisabled() bool { + if p == nil || p.Disabled == nil { + return false + } + return *p.Disabled +} + +// GetFork returns the Fork field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetFork() bool { + if p == nil || p.Fork == nil { + return false + } + return *p.Fork +} + +// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetForksCount() int { + if p == nil || p.ForksCount == nil { + return 0 + } + return *p.ForksCount +} + +// GetFullName returns the FullName field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetFullName() string { + if p == nil || p.FullName == nil { + return "" + } + return *p.FullName +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetGitURL() string { + if p == nil || p.GitURL == nil { + return "" + } + return *p.GitURL +} + +// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasDownloads() bool { + if p == nil || p.HasDownloads == nil { + return false + } + return *p.HasDownloads +} + +// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasIssues() bool { + if p == nil || p.HasIssues == nil { + return false + } + return *p.HasIssues +} + +// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasPages() bool { + if p == nil || p.HasPages == nil { + return false + } + return *p.HasPages +} + +// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHasWiki() bool { + if p == nil || p.HasWiki == nil { + return false + } + return *p.HasWiki +} + +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHomepage() string { + if p == nil || p.Homepage == nil { + return "" + } + return *p.Homepage +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetHTMLURL() string { + if p == nil || p.HTMLURL == nil { + return "" + } + return *p.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetID() int64 { + if p == nil || p.ID == nil { + return 0 + } + return *p.ID +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetLanguage() string { + if p == nil || p.Language == nil { + return "" + } + return *p.Language +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetMasterBranch() string { + if p == nil || p.MasterBranch == nil { + return "" + } + return *p.MasterBranch +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetName() string { + if p == nil || p.Name == nil { + return "" + } + return *p.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetNodeID() string { + if p == nil || p.NodeID == nil { + return "" + } + return *p.NodeID +} + +// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetOpenIssuesCount() int { + if p == nil || p.OpenIssuesCount == nil { + return 0 + } + return *p.OpenIssuesCount +} + +// GetOrganization returns the Organization field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetOrganization() string { + if p == nil || p.Organization == nil { + return "" + } + return *p.Organization +} + +// GetOwner returns the Owner field. +func (p *PushEventRepository) GetOwner() *User { + if p == nil { + return nil + } + return p.Owner +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPrivate() bool { + if p == nil || p.Private == nil { + return false + } + return *p.Private +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPullsURL() string { + if p == nil || p.PullsURL == nil { + return "" + } + return *p.PullsURL +} + +// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetPushedAt() Timestamp { + if p == nil || p.PushedAt == nil { + return Timestamp{} + } + return *p.PushedAt +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSize() int { + if p == nil || p.Size == nil { + return 0 + } + return *p.Size +} + +// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSSHURL() string { + if p == nil || p.SSHURL == nil { + return "" + } + return *p.SSHURL +} + +// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetStargazersCount() int { + if p == nil || p.StargazersCount == nil { + return 0 + } + return *p.StargazersCount +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetStatusesURL() string { + if p == nil || p.StatusesURL == nil { + return "" + } + return *p.StatusesURL +} + +// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetSVNURL() string { + if p == nil || p.SVNURL == nil { + return "" + } + return *p.SVNURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetUpdatedAt() Timestamp { + if p == nil || p.UpdatedAt == nil { + return Timestamp{} + } + return *p.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetURL() string { + if p == nil || p.URL == nil { + return "" + } + return *p.URL +} + +// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. +func (p *PushEventRepository) GetWatchersCount() int { + if p == nil || p.WatchersCount == nil { + return 0 + } + return *p.WatchersCount +} + +// GetActionsRunnerRegistration returns the ActionsRunnerRegistration field. +func (r *RateLimits) GetActionsRunnerRegistration() *Rate { + if r == nil { + return nil + } + return r.ActionsRunnerRegistration +} + +// GetCodeScanningUpload returns the CodeScanningUpload field. +func (r *RateLimits) GetCodeScanningUpload() *Rate { + if r == nil { + return nil + } + return r.CodeScanningUpload +} + +// GetCore returns the Core field. +func (r *RateLimits) GetCore() *Rate { + if r == nil { + return nil + } + return r.Core +} + +// GetGraphQL returns the GraphQL field. +func (r *RateLimits) GetGraphQL() *Rate { + if r == nil { + return nil + } + return r.GraphQL +} + +// GetIntegrationManifest returns the IntegrationManifest field. +func (r *RateLimits) GetIntegrationManifest() *Rate { + if r == nil { + return nil + } + return r.IntegrationManifest +} + +// GetSCIM returns the SCIM field. +func (r *RateLimits) GetSCIM() *Rate { + if r == nil { + return nil + } + return r.SCIM +} + +// GetSearch returns the Search field. +func (r *RateLimits) GetSearch() *Rate { + if r == nil { + return nil + } + return r.Search +} + +// GetSourceImport returns the SourceImport field. +func (r *RateLimits) GetSourceImport() *Rate { + if r == nil { + return nil + } + return r.SourceImport +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (r *Reaction) GetContent() string { + if r == nil || r.Content == nil { + return "" + } + return *r.Content +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Reaction) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Reaction) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetUser returns the User field. +func (r *Reaction) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetConfused returns the Confused field if it's non-nil, zero value otherwise. +func (r *Reactions) GetConfused() int { + if r == nil || r.Confused == nil { + return 0 + } + return *r.Confused +} + +// GetEyes returns the Eyes field if it's non-nil, zero value otherwise. +func (r *Reactions) GetEyes() int { + if r == nil || r.Eyes == nil { + return 0 + } + return *r.Eyes +} + +// GetHeart returns the Heart field if it's non-nil, zero value otherwise. +func (r *Reactions) GetHeart() int { + if r == nil || r.Heart == nil { + return 0 + } + return *r.Heart +} + +// GetHooray returns the Hooray field if it's non-nil, zero value otherwise. +func (r *Reactions) GetHooray() int { + if r == nil || r.Hooray == nil { + return 0 + } + return *r.Hooray +} + +// GetLaugh returns the Laugh field if it's non-nil, zero value otherwise. +func (r *Reactions) GetLaugh() int { + if r == nil || r.Laugh == nil { + return 0 + } + return *r.Laugh +} + +// GetMinusOne returns the MinusOne field if it's non-nil, zero value otherwise. +func (r *Reactions) GetMinusOne() int { + if r == nil || r.MinusOne == nil { + return 0 + } + return *r.MinusOne +} + +// GetPlusOne returns the PlusOne field if it's non-nil, zero value otherwise. +func (r *Reactions) GetPlusOne() int { + if r == nil || r.PlusOne == nil { + return 0 + } + return *r.PlusOne +} + +// GetRocket returns the Rocket field if it's non-nil, zero value otherwise. +func (r *Reactions) GetRocket() int { + if r == nil || r.Rocket == nil { + return 0 + } + return *r.Rocket +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (r *Reactions) GetTotalCount() int { + if r == nil || r.TotalCount == nil { + return 0 + } + return *r.TotalCount +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Reactions) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Reference) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetObject returns the Object field. +func (r *Reference) GetObject() *GitObject { + if r == nil { + return nil + } + return r.Object +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (r *Reference) GetRef() string { + if r == nil || r.Ref == nil { + return "" + } + return *r.Ref +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Reference) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (r *RegistrationToken) GetExpiresAt() Timestamp { + if r == nil || r.ExpiresAt == nil { + return Timestamp{} + } + return *r.ExpiresAt +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (r *RegistrationToken) GetToken() string { + if r == nil || r.Token == nil { + return "" + } + return *r.Token +} + +// GetBrowserDownloadURL returns the BrowserDownloadURL field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetBrowserDownloadURL() string { + if r == nil || r.BrowserDownloadURL == nil { + return "" + } + return *r.BrowserDownloadURL +} + +// GetContentType returns the ContentType field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetContentType() string { + if r == nil || r.ContentType == nil { + return "" + } + return *r.ContentType +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDownloadCount returns the DownloadCount field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetDownloadCount() int { + if r == nil || r.DownloadCount == nil { + return 0 + } + return *r.DownloadCount +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetLabel returns the Label field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetLabel() string { + if r == nil || r.Label == nil { + return "" + } + return *r.Label +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetUploader returns the Uploader field. +func (r *ReleaseAsset) GetUploader() *User { + if r == nil { + return nil + } + return r.Uploader +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *ReleaseAsset) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *ReleaseEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetInstallation returns the Installation field. +func (r *ReleaseEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetRelease returns the Release field. +func (r *ReleaseEvent) GetRelease() *RepositoryRelease { + if r == nil { + return nil + } + return r.Release +} + +// GetRepo returns the Repo field. +func (r *ReleaseEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *ReleaseEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetExpiresAt returns the ExpiresAt field if it's non-nil, zero value otherwise. +func (r *RemoveToken) GetExpiresAt() Timestamp { + if r == nil || r.ExpiresAt == nil { + return Timestamp{} + } + return *r.ExpiresAt +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (r *RemoveToken) GetToken() string { + if r == nil || r.Token == nil { + return "" + } + return *r.Token +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *Rename) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetTo returns the To field if it's non-nil, zero value otherwise. +func (r *Rename) GetTo() string { + if r == nil || r.To == nil { + return "" + } + return *r.To +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RenameOrgResponse) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RenameOrgResponse) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamRequest) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetBaseBranch returns the BaseBranch field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetBaseBranch() string { + if r == nil || r.BaseBranch == nil { + return "" + } + return *r.BaseBranch +} + +// GetMergeType returns the MergeType field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetMergeType() string { + if r == nil || r.MergeType == nil { + return "" + } + return *r.MergeType +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RepoMergeUpstreamResult) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (r *RepoName) GetFrom() string { + if r == nil || r.From == nil { + return "" + } + return *r.From +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (r *RepositoriesSearchResult) GetIncompleteResults() bool { + if r == nil || r.IncompleteResults == nil { + return false + } + return *r.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (r *RepositoriesSearchResult) GetTotal() int { + if r == nil || r.Total == nil { + return 0 + } + return *r.Total +} + +// GetAllowAutoMerge returns the AllowAutoMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowAutoMerge() bool { + if r == nil || r.AllowAutoMerge == nil { + return false + } + return *r.AllowAutoMerge +} + +// GetAllowForking returns the AllowForking field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowForking() bool { + if r == nil || r.AllowForking == nil { + return false + } + return *r.AllowForking +} + +// GetAllowMergeCommit returns the AllowMergeCommit field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowMergeCommit() bool { + if r == nil || r.AllowMergeCommit == nil { + return false + } + return *r.AllowMergeCommit +} + +// GetAllowRebaseMerge returns the AllowRebaseMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowRebaseMerge() bool { + if r == nil || r.AllowRebaseMerge == nil { + return false + } + return *r.AllowRebaseMerge +} + +// GetAllowSquashMerge returns the AllowSquashMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowSquashMerge() bool { + if r == nil || r.AllowSquashMerge == nil { + return false + } + return *r.AllowSquashMerge +} + +// GetAllowUpdateBranch returns the AllowUpdateBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetAllowUpdateBranch() bool { + if r == nil || r.AllowUpdateBranch == nil { + return false + } + return *r.AllowUpdateBranch +} + +// GetArchived returns the Archived field if it's non-nil, zero value otherwise. +func (r *Repository) GetArchived() bool { + if r == nil || r.Archived == nil { + return false + } + return *r.Archived +} + +// GetArchiveURL returns the ArchiveURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetArchiveURL() string { + if r == nil || r.ArchiveURL == nil { + return "" + } + return *r.ArchiveURL +} + +// GetAssigneesURL returns the AssigneesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetAssigneesURL() string { + if r == nil || r.AssigneesURL == nil { + return "" + } + return *r.AssigneesURL +} + +// GetAutoInit returns the AutoInit field if it's non-nil, zero value otherwise. +func (r *Repository) GetAutoInit() bool { + if r == nil || r.AutoInit == nil { + return false + } + return *r.AutoInit +} + +// GetBlobsURL returns the BlobsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetBlobsURL() string { + if r == nil || r.BlobsURL == nil { + return "" + } + return *r.BlobsURL +} + +// GetBranchesURL returns the BranchesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetBranchesURL() string { + if r == nil || r.BranchesURL == nil { + return "" + } + return *r.BranchesURL +} + +// GetCloneURL returns the CloneURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCloneURL() string { + if r == nil || r.CloneURL == nil { + return "" + } + return *r.CloneURL +} + +// GetCodeOfConduct returns the CodeOfConduct field. +func (r *Repository) GetCodeOfConduct() *CodeOfConduct { + if r == nil { + return nil + } + return r.CodeOfConduct +} + +// GetCollaboratorsURL returns the CollaboratorsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCollaboratorsURL() string { + if r == nil || r.CollaboratorsURL == nil { + return "" + } + return *r.CollaboratorsURL +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCommentsURL() string { + if r == nil || r.CommentsURL == nil { + return "" + } + return *r.CommentsURL +} + +// GetCommitsURL returns the CommitsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCommitsURL() string { + if r == nil || r.CommitsURL == nil { + return "" + } + return *r.CommitsURL +} + +// GetCompareURL returns the CompareURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetCompareURL() string { + if r == nil || r.CompareURL == nil { + return "" + } + return *r.CompareURL +} + +// GetContentsURL returns the ContentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetContentsURL() string { + if r == nil || r.ContentsURL == nil { + return "" + } + return *r.ContentsURL +} + +// GetContributorsURL returns the ContributorsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetContributorsURL() string { + if r == nil || r.ContributorsURL == nil { + return "" + } + return *r.ContributorsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDefaultBranch returns the DefaultBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetDefaultBranch() string { + if r == nil || r.DefaultBranch == nil { + return "" + } + return *r.DefaultBranch +} + +// GetDeleteBranchOnMerge returns the DeleteBranchOnMerge field if it's non-nil, zero value otherwise. +func (r *Repository) GetDeleteBranchOnMerge() bool { + if r == nil || r.DeleteBranchOnMerge == nil { + return false + } + return *r.DeleteBranchOnMerge +} + +// GetDeploymentsURL returns the DeploymentsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetDeploymentsURL() string { + if r == nil || r.DeploymentsURL == nil { + return "" + } + return *r.DeploymentsURL +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *Repository) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetDisabled returns the Disabled field if it's non-nil, zero value otherwise. +func (r *Repository) GetDisabled() bool { + if r == nil || r.Disabled == nil { + return false + } + return *r.Disabled +} + +// GetDownloadsURL returns the DownloadsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetDownloadsURL() string { + if r == nil || r.DownloadsURL == nil { + return "" + } + return *r.DownloadsURL +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetEventsURL() string { + if r == nil || r.EventsURL == nil { + return "" + } + return *r.EventsURL +} + +// GetFork returns the Fork field if it's non-nil, zero value otherwise. +func (r *Repository) GetFork() bool { + if r == nil || r.Fork == nil { + return false + } + return *r.Fork +} + +// GetForksCount returns the ForksCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetForksCount() int { + if r == nil || r.ForksCount == nil { + return 0 + } + return *r.ForksCount +} + +// GetForksURL returns the ForksURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetForksURL() string { + if r == nil || r.ForksURL == nil { + return "" + } + return *r.ForksURL +} + +// GetFullName returns the FullName field if it's non-nil, zero value otherwise. +func (r *Repository) GetFullName() string { + if r == nil || r.FullName == nil { + return "" + } + return *r.FullName +} + +// GetGitCommitsURL returns the GitCommitsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitCommitsURL() string { + if r == nil || r.GitCommitsURL == nil { + return "" + } + return *r.GitCommitsURL +} + +// GetGitignoreTemplate returns the GitignoreTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitignoreTemplate() string { + if r == nil || r.GitignoreTemplate == nil { + return "" + } + return *r.GitignoreTemplate +} + +// GetGitRefsURL returns the GitRefsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitRefsURL() string { + if r == nil || r.GitRefsURL == nil { + return "" + } + return *r.GitRefsURL +} + +// GetGitTagsURL returns the GitTagsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitTagsURL() string { + if r == nil || r.GitTagsURL == nil { + return "" + } + return *r.GitTagsURL +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHasDownloads returns the HasDownloads field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasDownloads() bool { + if r == nil || r.HasDownloads == nil { + return false + } + return *r.HasDownloads +} + +// GetHasIssues returns the HasIssues field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasIssues() bool { + if r == nil || r.HasIssues == nil { + return false + } + return *r.HasIssues +} + +// GetHasPages returns the HasPages field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasPages() bool { + if r == nil || r.HasPages == nil { + return false + } + return *r.HasPages +} + +// GetHasProjects returns the HasProjects field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasProjects() bool { + if r == nil || r.HasProjects == nil { + return false + } + return *r.HasProjects +} + +// GetHasWiki returns the HasWiki field if it's non-nil, zero value otherwise. +func (r *Repository) GetHasWiki() bool { + if r == nil || r.HasWiki == nil { + return false + } + return *r.HasWiki +} + +// GetHomepage returns the Homepage field if it's non-nil, zero value otherwise. +func (r *Repository) GetHomepage() string { + if r == nil || r.Homepage == nil { + return "" + } + return *r.Homepage +} + +// GetHooksURL returns the HooksURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetHooksURL() string { + if r == nil || r.HooksURL == nil { + return "" + } + return *r.HooksURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Repository) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetIssueCommentURL returns the IssueCommentURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssueCommentURL() string { + if r == nil || r.IssueCommentURL == nil { + return "" + } + return *r.IssueCommentURL +} + +// GetIssueEventsURL returns the IssueEventsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssueEventsURL() string { + if r == nil || r.IssueEventsURL == nil { + return "" + } + return *r.IssueEventsURL +} + +// GetIssuesURL returns the IssuesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetIssuesURL() string { + if r == nil || r.IssuesURL == nil { + return "" + } + return *r.IssuesURL +} + +// GetIsTemplate returns the IsTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetIsTemplate() bool { + if r == nil || r.IsTemplate == nil { + return false + } + return *r.IsTemplate +} + +// GetKeysURL returns the KeysURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetKeysURL() string { + if r == nil || r.KeysURL == nil { + return "" + } + return *r.KeysURL +} + +// GetLabelsURL returns the LabelsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetLabelsURL() string { + if r == nil || r.LabelsURL == nil { + return "" + } + return *r.LabelsURL +} + +// GetLanguage returns the Language field if it's non-nil, zero value otherwise. +func (r *Repository) GetLanguage() string { + if r == nil || r.Language == nil { + return "" + } + return *r.Language +} + +// GetLanguagesURL returns the LanguagesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetLanguagesURL() string { + if r == nil || r.LanguagesURL == nil { + return "" + } + return *r.LanguagesURL +} + +// GetLicense returns the License field. +func (r *Repository) GetLicense() *License { + if r == nil { + return nil + } + return r.License +} + +// GetLicenseTemplate returns the LicenseTemplate field if it's non-nil, zero value otherwise. +func (r *Repository) GetLicenseTemplate() string { + if r == nil || r.LicenseTemplate == nil { + return "" + } + return *r.LicenseTemplate +} + +// GetMasterBranch returns the MasterBranch field if it's non-nil, zero value otherwise. +func (r *Repository) GetMasterBranch() string { + if r == nil || r.MasterBranch == nil { + return "" + } + return *r.MasterBranch +} + +// GetMergesURL returns the MergesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMergesURL() string { + if r == nil || r.MergesURL == nil { + return "" + } + return *r.MergesURL +} + +// GetMilestonesURL returns the MilestonesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMilestonesURL() string { + if r == nil || r.MilestonesURL == nil { + return "" + } + return *r.MilestonesURL +} + +// GetMirrorURL returns the MirrorURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetMirrorURL() string { + if r == nil || r.MirrorURL == nil { + return "" + } + return *r.MirrorURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Repository) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNetworkCount returns the NetworkCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetNetworkCount() int { + if r == nil || r.NetworkCount == nil { + return 0 + } + return *r.NetworkCount +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *Repository) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetNotificationsURL returns the NotificationsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetNotificationsURL() string { + if r == nil || r.NotificationsURL == nil { + return "" + } + return *r.NotificationsURL +} + +// GetOpenIssues returns the OpenIssues field if it's non-nil, zero value otherwise. +func (r *Repository) GetOpenIssues() int { + if r == nil || r.OpenIssues == nil { + return 0 + } + return *r.OpenIssues +} + +// GetOpenIssuesCount returns the OpenIssuesCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetOpenIssuesCount() int { + if r == nil || r.OpenIssuesCount == nil { + return 0 + } + return *r.OpenIssuesCount +} + +// GetOrganization returns the Organization field. +func (r *Repository) GetOrganization() *Organization { + if r == nil { + return nil + } + return r.Organization +} + +// GetOwner returns the Owner field. +func (r *Repository) GetOwner() *User { + if r == nil { + return nil + } + return r.Owner +} + +// GetParent returns the Parent field. +func (r *Repository) GetParent() *Repository { + if r == nil { + return nil + } + return r.Parent +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (r *Repository) GetPermissions() map[string]bool { + if r == nil || r.Permissions == nil { + return map[string]bool{} + } + return r.Permissions +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (r *Repository) GetPrivate() bool { + if r == nil || r.Private == nil { + return false + } + return *r.Private +} + +// GetPullsURL returns the PullsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetPullsURL() string { + if r == nil || r.PullsURL == nil { + return "" + } + return *r.PullsURL +} + +// GetPushedAt returns the PushedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetPushedAt() Timestamp { + if r == nil || r.PushedAt == nil { + return Timestamp{} + } + return *r.PushedAt +} + +// GetReleasesURL returns the ReleasesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetReleasesURL() string { + if r == nil || r.ReleasesURL == nil { + return "" + } + return *r.ReleasesURL +} + +// GetSecurityAndAnalysis returns the SecurityAndAnalysis field. +func (r *Repository) GetSecurityAndAnalysis() *SecurityAndAnalysis { + if r == nil { + return nil + } + return r.SecurityAndAnalysis +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *Repository) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetSource returns the Source field. +func (r *Repository) GetSource() *Repository { + if r == nil { + return nil + } + return r.Source +} + +// GetSSHURL returns the SSHURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSSHURL() string { + if r == nil || r.SSHURL == nil { + return "" + } + return *r.SSHURL +} + +// GetStargazersCount returns the StargazersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetStargazersCount() int { + if r == nil || r.StargazersCount == nil { + return 0 + } + return *r.StargazersCount +} + +// GetStargazersURL returns the StargazersURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetStargazersURL() string { + if r == nil || r.StargazersURL == nil { + return "" + } + return *r.StargazersURL +} + +// GetStatusesURL returns the StatusesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetStatusesURL() string { + if r == nil || r.StatusesURL == nil { + return "" + } + return *r.StatusesURL +} + +// GetSubscribersCount returns the SubscribersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscribersCount() int { + if r == nil || r.SubscribersCount == nil { + return 0 + } + return *r.SubscribersCount +} + +// GetSubscribersURL returns the SubscribersURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscribersURL() string { + if r == nil || r.SubscribersURL == nil { + return "" + } + return *r.SubscribersURL +} + +// GetSubscriptionURL returns the SubscriptionURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSubscriptionURL() string { + if r == nil || r.SubscriptionURL == nil { + return "" + } + return *r.SubscriptionURL +} + +// GetSVNURL returns the SVNURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetSVNURL() string { + if r == nil || r.SVNURL == nil { + return "" + } + return *r.SVNURL +} + +// GetTagsURL returns the TagsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTagsURL() string { + if r == nil || r.TagsURL == nil { + return "" + } + return *r.TagsURL +} + +// GetTeamID returns the TeamID field if it's non-nil, zero value otherwise. +func (r *Repository) GetTeamID() int64 { + if r == nil || r.TeamID == nil { + return 0 + } + return *r.TeamID +} + +// GetTeamsURL returns the TeamsURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTeamsURL() string { + if r == nil || r.TeamsURL == nil { + return "" + } + return *r.TeamsURL +} + +// GetTemplateRepository returns the TemplateRepository field. +func (r *Repository) GetTemplateRepository() *Repository { + if r == nil { + return nil + } + return r.TemplateRepository +} + +// GetTreesURL returns the TreesURL field if it's non-nil, zero value otherwise. +func (r *Repository) GetTreesURL() string { + if r == nil || r.TreesURL == nil { + return "" + } + return *r.TreesURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *Repository) GetUpdatedAt() Timestamp { + if r == nil || r.UpdatedAt == nil { + return Timestamp{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *Repository) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (r *Repository) GetVisibility() string { + if r == nil || r.Visibility == nil { + return "" + } + return *r.Visibility +} + +// GetWatchers returns the Watchers field if it's non-nil, zero value otherwise. +func (r *Repository) GetWatchers() int { + if r == nil || r.Watchers == nil { + return 0 + } + return *r.Watchers +} + +// GetWatchersCount returns the WatchersCount field if it's non-nil, zero value otherwise. +func (r *Repository) GetWatchersCount() int { + if r == nil || r.WatchersCount == nil { + return 0 + } + return *r.WatchersCount +} + +// GetAdvancedSecurityCommitters returns the AdvancedSecurityCommitters field if it's non-nil, zero value otherwise. +func (r *RepositoryActiveCommitters) GetAdvancedSecurityCommitters() int { + if r == nil || r.AdvancedSecurityCommitters == nil { + return 0 + } + return *r.AdvancedSecurityCommitters +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryActiveCommitters) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetBody() string { + if r == nil || r.Body == nil { + return "" + } + return *r.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetCommitID() string { + if r == nil || r.CommitID == nil { + return "" + } + return *r.CommitID +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetCreatedAt() time.Time { + if r == nil || r.CreatedAt == nil { + return time.Time{} + } + return *r.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetPosition returns the Position field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetPosition() int { + if r == nil || r.Position == nil { + return 0 + } + return *r.Position +} + +// GetReactions returns the Reactions field. +func (r *RepositoryComment) GetReactions() *Reactions { + if r == nil { + return nil + } + return r.Reactions +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetUpdatedAt() time.Time { + if r == nil || r.UpdatedAt == nil { + return time.Time{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryComment) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetUser returns the User field. +func (r *RepositoryComment) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetAuthor returns the Author field. +func (r *RepositoryCommit) GetAuthor() *User { + if r == nil { + return nil + } + return r.Author +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetCommentsURL() string { + if r == nil || r.CommentsURL == nil { + return "" + } + return *r.CommentsURL +} + +// GetCommit returns the Commit field. +func (r *RepositoryCommit) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + +// GetCommitter returns the Committer field. +func (r *RepositoryCommit) GetCommitter() *User { + if r == nil { + return nil + } + return r.Committer +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetStats returns the Stats field. +func (r *RepositoryCommit) GetStats() *CommitStats { + if r == nil { + return nil + } + return r.Stats +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryCommit) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetEncoding() string { + if r == nil || r.Encoding == nil { + return "" + } + return *r.Encoding +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetTarget returns the Target field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetTarget() string { + if r == nil || r.Target == nil { + return "" + } + return *r.Target +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryContent) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetAuthor returns the Author field. +func (r *RepositoryContentFileOptions) GetAuthor() *CommitAuthor { + if r == nil { + return nil + } + return r.Author +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetCommitter returns the Committer field. +func (r *RepositoryContentFileOptions) GetCommitter() *CommitAuthor { + if r == nil { + return nil + } + return r.Committer +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetMessage() string { + if r == nil || r.Message == nil { + return "" + } + return *r.Message +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryContentFileOptions) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetContent returns the Content field. +func (r *RepositoryContentResponse) GetContent() *RepositoryContent { + if r == nil { + return nil + } + return r.Content +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryDispatchEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetBranch returns the Branch field if it's non-nil, zero value otherwise. +func (r *RepositoryDispatchEvent) GetBranch() string { + if r == nil || r.Branch == nil { + return "" + } + return *r.Branch +} + +// GetInstallation returns the Installation field. +func (r *RepositoryDispatchEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryDispatchEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryDispatchEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryDispatchEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetChanges returns the Changes field. +func (r *RepositoryEvent) GetChanges() *EditChange { + if r == nil { + return nil + } + return r.Changes +} + +// GetInstallation returns the Installation field. +func (r *RepositoryEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetOrg returns the Org field. +func (r *RepositoryEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetOrg returns the Org field. +func (r *RepositoryImportEvent) GetOrg() *Organization { + if r == nil { + return nil + } + return r.Org +} + +// GetRepo returns the Repo field. +func (r *RepositoryImportEvent) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetSender returns the Sender field. +func (r *RepositoryImportEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (r *RepositoryImportEvent) GetStatus() string { + if r == nil || r.Status == nil { + return "" + } + return *r.Status +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetInvitee returns the Invitee field. +func (r *RepositoryInvitation) GetInvitee() *User { + if r == nil { + return nil + } + return r.Invitee +} + +// GetInviter returns the Inviter field. +func (r *RepositoryInvitation) GetInviter() *User { + if r == nil { + return nil + } + return r.Inviter +} + +// GetPermissions returns the Permissions field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetPermissions() string { + if r == nil || r.Permissions == nil { + return "" + } + return *r.Permissions +} + +// GetRepo returns the Repo field. +func (r *RepositoryInvitation) GetRepo() *Repository { + if r == nil { + return nil + } + return r.Repo +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryInvitation) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetContent() string { + if r == nil || r.Content == nil { + return "" + } + return *r.Content +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetEncoding returns the Encoding field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetEncoding() string { + if r == nil || r.Encoding == nil { + return "" + } + return *r.Encoding +} + +// GetGitURL returns the GitURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetGitURL() string { + if r == nil || r.GitURL == nil { + return "" + } + return *r.GitURL +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetLicense returns the License field. +func (r *RepositoryLicense) GetLicense() *License { + if r == nil { + return nil + } + return r.License +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetPath() string { + if r == nil || r.Path == nil { + return "" + } + return *r.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetSHA() string { + if r == nil || r.SHA == nil { + return "" + } + return *r.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetSize() int { + if r == nil || r.Size == nil { + return 0 + } + return *r.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryLicense) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetBase returns the Base field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetBase() string { + if r == nil || r.Base == nil { + return "" + } + return *r.Base +} + +// GetCommitMessage returns the CommitMessage field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetCommitMessage() string { + if r == nil || r.CommitMessage == nil { + return "" + } + return *r.CommitMessage +} + +// GetHead returns the Head field if it's non-nil, zero value otherwise. +func (r *RepositoryMergeRequest) GetHead() string { + if r == nil || r.Head == nil { + return "" + } + return *r.Head +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (r *RepositoryPermissionLevel) GetPermission() string { + if r == nil || r.Permission == nil { + return "" + } + return *r.Permission +} + +// GetUser returns the User field. +func (r *RepositoryPermissionLevel) GetUser() *User { + if r == nil { + return nil + } + return r.User +} + +// GetAssetsURL returns the AssetsURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetAssetsURL() string { + if r == nil || r.AssetsURL == nil { + return "" + } + return *r.AssetsURL +} + +// GetAuthor returns the Author field. +func (r *RepositoryRelease) GetAuthor() *User { + if r == nil { + return nil + } + return r.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetBody() string { + if r == nil || r.Body == nil { + return "" + } + return *r.Body +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDiscussionCategoryName returns the DiscussionCategoryName field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetDiscussionCategoryName() string { + if r == nil || r.DiscussionCategoryName == nil { + return "" + } + return *r.DiscussionCategoryName +} + +// GetDraft returns the Draft field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetDraft() bool { + if r == nil || r.Draft == nil { + return false + } + return *r.Draft +} + +// GetGenerateReleaseNotes returns the GenerateReleaseNotes field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetGenerateReleaseNotes() bool { + if r == nil || r.GenerateReleaseNotes == nil { + return false + } + return *r.GenerateReleaseNotes +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetHTMLURL() string { + if r == nil || r.HTMLURL == nil { + return "" + } + return *r.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetPrerelease returns the Prerelease field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetPrerelease() bool { + if r == nil || r.Prerelease == nil { + return false + } + return *r.Prerelease +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetPublishedAt() Timestamp { + if r == nil || r.PublishedAt == nil { + return Timestamp{} + } + return *r.PublishedAt +} + +// GetTagName returns the TagName field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTagName() string { + if r == nil || r.TagName == nil { + return "" + } + return *r.TagName +} + +// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTarballURL() string { + if r == nil || r.TarballURL == nil { + return "" + } + return *r.TarballURL +} + +// GetTargetCommitish returns the TargetCommitish field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetTargetCommitish() string { + if r == nil || r.TargetCommitish == nil { + return "" + } + return *r.TargetCommitish +} + +// GetUploadURL returns the UploadURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetUploadURL() string { + if r == nil || r.UploadURL == nil { + return "" + } + return *r.UploadURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryRelease) GetZipballURL() string { + if r == nil || r.ZipballURL == nil { + return "" + } + return *r.ZipballURL +} + +// GetCommit returns the Commit field. +func (r *RepositoryTag) GetCommit() *Commit { + if r == nil { + return nil + } + return r.Commit +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetTarballURL returns the TarballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetTarballURL() string { + if r == nil || r.TarballURL == nil { + return "" + } + return *r.TarballURL +} + +// GetZipballURL returns the ZipballURL field if it's non-nil, zero value otherwise. +func (r *RepositoryTag) GetZipballURL() string { + if r == nil || r.ZipballURL == nil { + return "" + } + return *r.ZipballURL +} + +// GetAffectedPackageName returns the AffectedPackageName field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetAffectedPackageName() string { + if r == nil || r.AffectedPackageName == nil { + return "" + } + return *r.AffectedPackageName +} + +// GetAffectedRange returns the AffectedRange field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetAffectedRange() string { + if r == nil || r.AffectedRange == nil { + return "" + } + return *r.AffectedRange +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetCreatedAt() Timestamp { + if r == nil || r.CreatedAt == nil { + return Timestamp{} + } + return *r.CreatedAt +} + +// GetDismissedAt returns the DismissedAt field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetDismissedAt() Timestamp { + if r == nil || r.DismissedAt == nil { + return Timestamp{} + } + return *r.DismissedAt +} + +// GetDismisser returns the Dismisser field. +func (r *RepositoryVulnerabilityAlert) GetDismisser() *User { + if r == nil { + return nil + } + return r.Dismisser +} + +// GetDismissReason returns the DismissReason field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetDismissReason() string { + if r == nil || r.DismissReason == nil { + return "" + } + return *r.DismissReason +} + +// GetExternalIdentifier returns the ExternalIdentifier field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetExternalIdentifier() string { + if r == nil || r.ExternalIdentifier == nil { + return "" + } + return *r.ExternalIdentifier +} + +// GetExternalReference returns the ExternalReference field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetExternalReference() string { + if r == nil || r.ExternalReference == nil { + return "" + } + return *r.ExternalReference +} + +// GetFixedIn returns the FixedIn field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetFixedIn() string { + if r == nil || r.FixedIn == nil { + return "" + } + return *r.FixedIn +} + +// GetGitHubSecurityAdvisoryID returns the GitHubSecurityAdvisoryID field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetGitHubSecurityAdvisoryID() string { + if r == nil || r.GitHubSecurityAdvisoryID == nil { + return "" + } + return *r.GitHubSecurityAdvisoryID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlert) GetSeverity() string { + if r == nil || r.Severity == nil { + return "" + } + return *r.Severity +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (r *RepositoryVulnerabilityAlertEvent) GetAction() string { + if r == nil || r.Action == nil { + return "" + } + return *r.Action +} + +// GetAlert returns the Alert field. +func (r *RepositoryVulnerabilityAlertEvent) GetAlert() *RepositoryVulnerabilityAlert { + if r == nil { + return nil + } + return r.Alert +} + +// GetInstallation returns the Installation field. +func (r *RepositoryVulnerabilityAlertEvent) GetInstallation() *Installation { + if r == nil { + return nil + } + return r.Installation +} + +// GetRepository returns the Repository field. +func (r *RepositoryVulnerabilityAlertEvent) GetRepository() *Repository { + if r == nil { + return nil + } + return r.Repository +} + +// GetSender returns the Sender field. +func (r *RepositoryVulnerabilityAlertEvent) GetSender() *User { + if r == nil { + return nil + } + return r.Sender +} + +// GetForkRepos returns the ForkRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetForkRepos() int { + if r == nil || r.ForkRepos == nil { + return 0 + } + return *r.ForkRepos +} + +// GetOrgRepos returns the OrgRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetOrgRepos() int { + if r == nil || r.OrgRepos == nil { + return 0 + } + return *r.OrgRepos +} + +// GetRootRepos returns the RootRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetRootRepos() int { + if r == nil || r.RootRepos == nil { + return 0 + } + return *r.RootRepos +} + +// GetTotalPushes returns the TotalPushes field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalPushes() int { + if r == nil || r.TotalPushes == nil { + return 0 + } + return *r.TotalPushes +} + +// GetTotalRepos returns the TotalRepos field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalRepos() int { + if r == nil || r.TotalRepos == nil { + return 0 + } + return *r.TotalRepos +} + +// GetTotalWikis returns the TotalWikis field if it's non-nil, zero value otherwise. +func (r *RepoStats) GetTotalWikis() int { + if r == nil || r.TotalWikis == nil { + return 0 + } + return *r.TotalWikis +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetAvatarURL() string { + if r == nil || r.AvatarURL == nil { + return "" + } + return *r.AvatarURL +} + +// GetContext returns the Context field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetContext() string { + if r == nil || r.Context == nil { + return "" + } + return *r.Context +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetCreatedAt() time.Time { + if r == nil || r.CreatedAt == nil { + return time.Time{} + } + return *r.CreatedAt +} + +// GetCreator returns the Creator field. +func (r *RepoStatus) GetCreator() *User { + if r == nil { + return nil + } + return r.Creator +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetState() string { + if r == nil || r.State == nil { + return "" + } + return *r.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetTargetURL() string { + if r == nil || r.TargetURL == nil { + return "" + } + return *r.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetUpdatedAt() time.Time { + if r == nil || r.UpdatedAt == nil { + return time.Time{} + } + return *r.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (r *RepoStatus) GetURL() string { + if r == nil || r.URL == nil { + return "" + } + return *r.URL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RequiredReviewer) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetAppID returns the AppID field if it's non-nil, zero value otherwise. +func (r *RequiredStatusCheck) GetAppID() int64 { + if r == nil || r.AppID == nil { + return 0 + } + return *r.AppID +} + +// GetStrict returns the Strict field if it's non-nil, zero value otherwise. +func (r *RequiredStatusChecksRequest) GetStrict() bool { + if r == nil || r.Strict == nil { + return false + } + return *r.Strict +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (r *ReviewersRequest) GetNodeID() string { + if r == nil || r.NodeID == nil { + return "" + } + return *r.NodeID +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *Rule) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetFullDescription returns the FullDescription field if it's non-nil, zero value otherwise. +func (r *Rule) GetFullDescription() string { + if r == nil || r.FullDescription == nil { + return "" + } + return *r.FullDescription +} + +// GetHelp returns the Help field if it's non-nil, zero value otherwise. +func (r *Rule) GetHelp() string { + if r == nil || r.Help == nil { + return "" + } + return *r.Help +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Rule) GetID() string { + if r == nil || r.ID == nil { + return "" + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Rule) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetSecuritySeverityLevel returns the SecuritySeverityLevel field if it's non-nil, zero value otherwise. +func (r *Rule) GetSecuritySeverityLevel() string { + if r == nil || r.SecuritySeverityLevel == nil { + return "" + } + return *r.SecuritySeverityLevel +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (r *Rule) GetSeverity() string { + if r == nil || r.Severity == nil { + return "" + } + return *r.Severity +} + +// GetBusy returns the Busy field if it's non-nil, zero value otherwise. +func (r *Runner) GetBusy() bool { + if r == nil || r.Busy == nil { + return false + } + return *r.Busy +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *Runner) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *Runner) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetOS returns the OS field if it's non-nil, zero value otherwise. +func (r *Runner) GetOS() string { + if r == nil || r.OS == nil { + return "" + } + return *r.OS +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (r *Runner) GetStatus() string { + if r == nil || r.Status == nil { + return "" + } + return *r.Status +} + +// GetArchitecture returns the Architecture field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetArchitecture() string { + if r == nil || r.Architecture == nil { + return "" + } + return *r.Architecture +} + +// GetDownloadURL returns the DownloadURL field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetDownloadURL() string { + if r == nil || r.DownloadURL == nil { + return "" + } + return *r.DownloadURL +} + +// GetFilename returns the Filename field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetFilename() string { + if r == nil || r.Filename == nil { + return "" + } + return *r.Filename +} + +// GetOS returns the OS field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetOS() string { + if r == nil || r.OS == nil { + return "" + } + return *r.OS +} + +// GetSHA256Checksum returns the SHA256Checksum field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetSHA256Checksum() string { + if r == nil || r.SHA256Checksum == nil { + return "" + } + return *r.SHA256Checksum +} + +// GetTempDownloadToken returns the TempDownloadToken field if it's non-nil, zero value otherwise. +func (r *RunnerApplicationDownload) GetTempDownloadToken() string { + if r == nil || r.TempDownloadToken == nil { + return "" + } + return *r.TempDownloadToken +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetAllowsPublicRepositories() bool { + if r == nil || r.AllowsPublicRepositories == nil { + return false + } + return *r.AllowsPublicRepositories +} + +// GetDefault returns the Default field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetDefault() bool { + if r == nil || r.Default == nil { + return false + } + return *r.Default +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetInherited returns the Inherited field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetInherited() bool { + if r == nil || r.Inherited == nil { + return false + } + return *r.Inherited +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetRunnersURL returns the RunnersURL field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetRunnersURL() string { + if r == nil || r.RunnersURL == nil { + return "" + } + return *r.RunnersURL +} + +// GetSelectedRepositoriesURL returns the SelectedRepositoriesURL field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetSelectedRepositoriesURL() string { + if r == nil || r.SelectedRepositoriesURL == nil { + return "" + } + return *r.SelectedRepositoriesURL +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (r *RunnerGroup) GetVisibility() string { + if r == nil || r.Visibility == nil { + return "" + } + return *r.Visibility +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetID() int64 { + if r == nil || r.ID == nil { + return 0 + } + return *r.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (r *RunnerLabels) GetType() string { + if r == nil || r.Type == nil { + return "" + } + return *r.Type +} + +// GetCheckoutURI returns the CheckoutURI field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetCheckoutURI() string { + if s == nil || s.CheckoutURI == nil { + return "" + } + return *s.CheckoutURI +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetRef() string { + if s == nil || s.Ref == nil { + return "" + } + return *s.Ref +} + +// GetSarif returns the Sarif field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetSarif() string { + if s == nil || s.Sarif == nil { + return "" + } + return *s.Sarif +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetStartedAt() Timestamp { + if s == nil || s.StartedAt == nil { + return Timestamp{} + } + return *s.StartedAt +} + +// GetToolName returns the ToolName field if it's non-nil, zero value otherwise. +func (s *SarifAnalysis) GetToolName() string { + if s == nil || s.ToolName == nil { + return "" + } + return *s.ToolName +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SarifID) GetID() string { + if s == nil || s.ID == nil { + return "" + } + return *s.ID +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SarifID) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetAnalysisKey returns the AnalysisKey field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetAnalysisKey() string { + if s == nil || s.AnalysisKey == nil { + return "" + } + return *s.AnalysisKey +} + +// GetCategory returns the Category field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCategory() string { + if s == nil || s.Category == nil { + return "" + } + return *s.Category +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetDeletable returns the Deletable field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetDeletable() bool { + if s == nil || s.Deletable == nil { + return false + } + return *s.Deletable +} + +// GetEnvironment returns the Environment field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetEnvironment() string { + if s == nil || s.Environment == nil { + return "" + } + return *s.Environment +} + +// GetError returns the Error field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetError() string { + if s == nil || s.Error == nil { + return "" + } + return *s.Error +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetRef() string { + if s == nil || s.Ref == nil { + return "" + } + return *s.Ref +} + +// GetResultsCount returns the ResultsCount field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetResultsCount() int { + if s == nil || s.ResultsCount == nil { + return 0 + } + return *s.ResultsCount +} + +// GetRulesCount returns the RulesCount field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetRulesCount() int { + if s == nil || s.RulesCount == nil { + return 0 + } + return *s.RulesCount +} + +// GetSarifID returns the SarifID field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetSarifID() string { + if s == nil || s.SarifID == nil { + return "" + } + return *s.SarifID +} + +// GetTool returns the Tool field. +func (s *ScanningAnalysis) GetTool() *Tool { + if s == nil { + return nil + } + return s.Tool +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetWarning returns the Warning field if it's non-nil, zero value otherwise. +func (s *ScanningAnalysis) GetWarning() string { + if s == nil || s.Warning == nil { + return "" + } + return *s.Warning +} + +// GetActive returns the Active field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetActive() bool { + if s == nil || s.Active == nil { + return false + } + return *s.Active +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetDisplayName() string { + if s == nil || s.DisplayName == nil { + return "" + } + return *s.DisplayName +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (s *SCIMUserAttributes) GetExternalID() string { + if s == nil || s.ExternalID == nil { + return "" + } + return *s.ExternalID +} + +// GetPrimary returns the Primary field if it's non-nil, zero value otherwise. +func (s *SCIMUserEmail) GetPrimary() bool { + if s == nil || s.Primary == nil { + return false + } + return *s.Primary +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *SCIMUserEmail) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetFormatted returns the Formatted field if it's non-nil, zero value otherwise. +func (s *SCIMUserName) GetFormatted() string { + if s == nil || s.Formatted == nil { + return "" + } + return *s.Formatted +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (s *SecretScanning) GetStatus() string { + if s == nil || s.Status == nil { + return "" + } + return *s.Status +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetHTMLURL() string { + if s == nil || s.HTMLURL == nil { + return "" + } + return *s.HTMLURL +} + +// GetLocationsURL returns the LocationsURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetLocationsURL() string { + if s == nil || s.LocationsURL == nil { + return "" + } + return *s.LocationsURL +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetNumber() int { + if s == nil || s.Number == nil { + return 0 + } + return *s.Number +} + +// GetResolution returns the Resolution field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetResolution() string { + if s == nil || s.Resolution == nil { + return "" + } + return *s.Resolution +} + +// GetResolvedAt returns the ResolvedAt field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetResolvedAt() Timestamp { + if s == nil || s.ResolvedAt == nil { + return Timestamp{} + } + return *s.ResolvedAt +} + +// GetResolvedBy returns the ResolvedBy field. +func (s *SecretScanningAlert) GetResolvedBy() *User { + if s == nil { + return nil + } + return s.ResolvedBy +} + +// GetSecret returns the Secret field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetSecret() string { + if s == nil || s.Secret == nil { + return "" + } + return *s.Secret +} + +// GetSecretType returns the SecretType field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetSecretType() string { + if s == nil || s.SecretType == nil { + return "" + } + return *s.SecretType +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlert) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetAlert returns the Alert field. +func (s *SecretScanningAlertEvent) GetAlert() *SecretScanningAlert { + if s == nil { + return nil + } + return s.Alert +} + +// GetEnterprise returns the Enterprise field. +func (s *SecretScanningAlertEvent) GetEnterprise() *Enterprise { + if s == nil { + return nil + } + return s.Enterprise +} + +// GetInstallation returns the Installation field. +func (s *SecretScanningAlertEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrganization returns the Organization field. +func (s *SecretScanningAlertEvent) GetOrganization() *Organization { + if s == nil { + return nil + } + return s.Organization +} + +// GetRepo returns the Repo field. +func (s *SecretScanningAlertEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *SecretScanningAlertEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetDetails returns the Details field. +func (s *SecretScanningAlertLocation) GetDetails() *SecretScanningAlertLocationDetails { + if s == nil { + return nil + } + return s.Details +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocation) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetBlobSHA returns the BlobSHA field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetBlobSHA() string { + if s == nil || s.BlobSHA == nil { + return "" + } + return *s.BlobSHA +} + +// GetBlobURL returns the BlobURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetBlobURL() string { + if s == nil || s.BlobURL == nil { + return "" + } + return *s.BlobURL +} + +// GetCommitSHA returns the CommitSHA field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetCommitSHA() string { + if s == nil || s.CommitSHA == nil { + return "" + } + return *s.CommitSHA +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetCommitURL() string { + if s == nil || s.CommitURL == nil { + return "" + } + return *s.CommitURL +} + +// GetEndColumn returns the EndColumn field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetEndColumn() int { + if s == nil || s.EndColumn == nil { + return 0 + } + return *s.EndColumn +} + +// GetEndLine returns the EndLine field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetEndLine() int { + if s == nil || s.EndLine == nil { + return 0 + } + return *s.EndLine +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetPath() string { + if s == nil || s.Path == nil { + return "" + } + return *s.Path +} + +// GetStartColumn returns the StartColumn field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetStartColumn() int { + if s == nil || s.StartColumn == nil { + return 0 + } + return *s.StartColumn +} + +// GetStartline returns the Startline field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertLocationDetails) GetStartline() int { + if s == nil || s.Startline == nil { + return 0 + } + return *s.Startline +} + +// GetResolution returns the Resolution field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertUpdateOptions) GetResolution() string { + if s == nil || s.Resolution == nil { + return "" + } + return *s.Resolution +} + +// GetSecretType returns the SecretType field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertUpdateOptions) GetSecretType() string { + if s == nil || s.SecretType == nil { + return "" + } + return *s.SecretType +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *SecretScanningAlertUpdateOptions) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetDescription() string { + if s == nil || s.Description == nil { + return "" + } + return *s.Description +} + +// GetGHSAID returns the GHSAID field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetGHSAID() string { + if s == nil || s.GHSAID == nil { + return "" + } + return *s.GHSAID +} + +// GetPublishedAt returns the PublishedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetPublishedAt() Timestamp { + if s == nil || s.PublishedAt == nil { + return Timestamp{} + } + return *s.PublishedAt +} + +// GetSeverity returns the Severity field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetSeverity() string { + if s == nil || s.Severity == nil { + return "" + } + return *s.Severity +} + +// GetSummary returns the Summary field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetSummary() string { + if s == nil || s.Summary == nil { + return "" + } + return *s.Summary +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetWithdrawnAt returns the WithdrawnAt field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisory) GetWithdrawnAt() Timestamp { + if s == nil || s.WithdrawnAt == nil { + return Timestamp{} + } + return *s.WithdrawnAt +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *SecurityAdvisoryEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetSecurityAdvisory returns the SecurityAdvisory field. +func (s *SecurityAdvisoryEvent) GetSecurityAdvisory() *SecurityAdvisory { + if s == nil { + return nil + } + return s.SecurityAdvisory +} + +// GetAdvancedSecurity returns the AdvancedSecurity field. +func (s *SecurityAndAnalysis) GetAdvancedSecurity() *AdvancedSecurity { + if s == nil { + return nil + } + return s.AdvancedSecurity +} + +// GetSecretScanning returns the SecretScanning field. +func (s *SecurityAndAnalysis) GetSecretScanning() *SecretScanning { + if s == nil { + return nil + } + return s.SecretScanning +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (s *SelectedReposList) GetTotalCount() int { + if s == nil || s.TotalCount == nil { + return 0 + } + return *s.TotalCount +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *ServiceHook) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise. +func (s *SignaturesProtectedBranch) GetEnabled() bool { + if s == nil || s.Enabled == nil { + return false + } + return *s.Enabled +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SignaturesProtectedBranch) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetPayload returns the Payload field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetPayload() string { + if s == nil || s.Payload == nil { + return "" + } + return *s.Payload +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetReason() string { + if s == nil || s.Reason == nil { + return "" + } + return *s.Reason +} + +// GetSignature returns the Signature field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetSignature() string { + if s == nil || s.Signature == nil { + return "" + } + return *s.Signature +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (s *SignatureVerification) GetVerified() bool { + if s == nil || s.Verified == nil { + return false + } + return *s.Verified +} + +// GetActor returns the Actor field. +func (s *Source) GetActor() *User { + if s == nil { + return nil + } + return s.Actor +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *Source) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetIssue returns the Issue field. +func (s *Source) GetIssue() *Issue { + if s == nil { + return nil + } + return s.Issue +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (s *Source) GetType() string { + if s == nil || s.Type == nil { + return "" + } + return *s.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *Source) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetEmail() string { + if s == nil || s.Email == nil { + return "" + } + return *s.Email +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetImportURL returns the ImportURL field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetImportURL() string { + if s == nil || s.ImportURL == nil { + return "" + } + return *s.ImportURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetRemoteID returns the RemoteID field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetRemoteID() string { + if s == nil || s.RemoteID == nil { + return "" + } + return *s.RemoteID +} + +// GetRemoteName returns the RemoteName field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetRemoteName() string { + if s == nil || s.RemoteName == nil { + return "" + } + return *s.RemoteName +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *SourceImportAuthor) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (s *StarEvent) GetAction() string { + if s == nil || s.Action == nil { + return "" + } + return *s.Action +} + +// GetInstallation returns the Installation field. +func (s *StarEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetOrg returns the Org field. +func (s *StarEvent) GetOrg() *Organization { + if s == nil { + return nil + } + return s.Org +} + +// GetRepo returns the Repo field. +func (s *StarEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *StarEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *StarEvent) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *Stargazer) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetUser returns the User field. +func (s *Stargazer) GetUser() *User { + if s == nil { + return nil + } + return s.User +} + +// GetRepository returns the Repository field. +func (s *StarredRepository) GetRepository() *Repository { + if s == nil { + return nil + } + return s.Repository +} + +// GetStarredAt returns the StarredAt field if it's non-nil, zero value otherwise. +func (s *StarredRepository) GetStarredAt() Timestamp { + if s == nil || s.StarredAt == nil { + return Timestamp{} + } + return *s.StarredAt +} + +// GetCommit returns the Commit field. +func (s *StatusEvent) GetCommit() *RepositoryCommit { + if s == nil { + return nil + } + return s.Commit +} + +// GetContext returns the Context field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetContext() string { + if s == nil || s.Context == nil { + return "" + } + return *s.Context +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetDescription() string { + if s == nil || s.Description == nil { + return "" + } + return *s.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetID() int64 { + if s == nil || s.ID == nil { + return 0 + } + return *s.ID +} + +// GetInstallation returns the Installation field. +func (s *StatusEvent) GetInstallation() *Installation { + if s == nil { + return nil + } + return s.Installation +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetName() string { + if s == nil || s.Name == nil { + return "" + } + return *s.Name +} + +// GetRepo returns the Repo field. +func (s *StatusEvent) GetRepo() *Repository { + if s == nil { + return nil + } + return s.Repo +} + +// GetSender returns the Sender field. +func (s *StatusEvent) GetSender() *User { + if s == nil { + return nil + } + return s.Sender +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetSHA() string { + if s == nil || s.SHA == nil { + return "" + } + return *s.SHA +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetState() string { + if s == nil || s.State == nil { + return "" + } + return *s.State +} + +// GetTargetURL returns the TargetURL field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetTargetURL() string { + if s == nil || s.TargetURL == nil { + return "" + } + return *s.TargetURL +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (s *StatusEvent) GetUpdatedAt() Timestamp { + if s == nil || s.UpdatedAt == nil { + return Timestamp{} + } + return *s.UpdatedAt +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (s *Subscription) GetCreatedAt() Timestamp { + if s == nil || s.CreatedAt == nil { + return Timestamp{} + } + return *s.CreatedAt +} + +// GetIgnored returns the Ignored field if it's non-nil, zero value otherwise. +func (s *Subscription) GetIgnored() bool { + if s == nil || s.Ignored == nil { + return false + } + return *s.Ignored +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (s *Subscription) GetReason() string { + if s == nil || s.Reason == nil { + return "" + } + return *s.Reason +} + +// GetRepositoryURL returns the RepositoryURL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetRepositoryURL() string { + if s == nil || s.RepositoryURL == nil { + return "" + } + return *s.RepositoryURL +} + +// GetSubscribed returns the Subscribed field if it's non-nil, zero value otherwise. +func (s *Subscription) GetSubscribed() bool { + if s == nil || s.Subscribed == nil { + return false + } + return *s.Subscribed +} + +// GetThreadURL returns the ThreadURL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetThreadURL() string { + if s == nil || s.ThreadURL == nil { + return "" + } + return *s.ThreadURL +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (s *Subscription) GetURL() string { + if s == nil || s.URL == nil { + return "" + } + return *s.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (t *Tag) GetMessage() string { + if t == nil || t.Message == nil { + return "" + } + return *t.Message +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *Tag) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetObject returns the Object field. +func (t *Tag) GetObject() *GitObject { + if t == nil { + return nil + } + return t.Object +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Tag) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetTag returns the Tag field if it's non-nil, zero value otherwise. +func (t *Tag) GetTag() string { + if t == nil || t.Tag == nil { + return "" + } + return *t.Tag +} + +// GetTagger returns the Tagger field. +func (t *Tag) GetTagger() *CommitAuthor { + if t == nil { + return nil + } + return t.Tagger +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Tag) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetVerification returns the Verification field. +func (t *Tag) GetVerification() *SignatureVerification { + if t == nil { + return nil + } + return t.Verification +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetCompletedAt() Timestamp { + if t == nil || t.CompletedAt == nil { + return Timestamp{} + } + return *t.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetConclusion() string { + if t == nil || t.Conclusion == nil { + return "" + } + return *t.Conclusion +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetNumber() int64 { + if t == nil || t.Number == nil { + return 0 + } + return *t.Number +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetStartedAt() Timestamp { + if t == nil || t.StartedAt == nil { + return Timestamp{} + } + return *t.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (t *TaskStep) GetStatus() string { + if t == nil || t.Status == nil { + return "" + } + return *t.Status +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *Team) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (t *Team) GetHTMLURL() string { + if t == nil || t.HTMLURL == nil { + return "" + } + return *t.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *Team) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (t *Team) GetLDAPDN() string { + if t == nil || t.LDAPDN == nil { + return "" + } + return *t.LDAPDN +} + +// GetMembersCount returns the MembersCount field if it's non-nil, zero value otherwise. +func (t *Team) GetMembersCount() int { + if t == nil || t.MembersCount == nil { + return 0 + } + return *t.MembersCount +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (t *Team) GetMembersURL() string { + if t == nil || t.MembersURL == nil { + return "" + } + return *t.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *Team) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *Team) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetOrganization returns the Organization field. +func (t *Team) GetOrganization() *Organization { + if t == nil { + return nil + } + return t.Organization +} + +// GetParent returns the Parent field. +func (t *Team) GetParent() *Team { + if t == nil { + return nil + } + return t.Parent +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *Team) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (t *Team) GetPermissions() map[string]bool { + if t == nil || t.Permissions == nil { + return map[string]bool{} + } + return t.Permissions +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (t *Team) GetPrivacy() string { + if t == nil || t.Privacy == nil { + return "" + } + return *t.Privacy +} + +// GetReposCount returns the ReposCount field if it's non-nil, zero value otherwise. +func (t *Team) GetReposCount() int { + if t == nil || t.ReposCount == nil { + return 0 + } + return *t.ReposCount +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (t *Team) GetRepositoriesURL() string { + if t == nil || t.RepositoriesURL == nil { + return "" + } + return *t.RepositoriesURL +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (t *Team) GetSlug() string { + if t == nil || t.Slug == nil { + return "" + } + return *t.Slug +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Team) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetInstallation returns the Installation field. +func (t *TeamAddEvent) GetInstallation() *Installation { + if t == nil { + return nil + } + return t.Installation +} + +// GetOrg returns the Org field. +func (t *TeamAddEvent) GetOrg() *Organization { + if t == nil { + return nil + } + return t.Org +} + +// GetRepo returns the Repo field. +func (t *TeamAddEvent) GetRepo() *Repository { + if t == nil { + return nil + } + return t.Repo +} + +// GetSender returns the Sender field. +func (t *TeamAddEvent) GetSender() *User { + if t == nil { + return nil + } + return t.Sender +} + +// GetTeam returns the Team field. +func (t *TeamAddEvent) GetTeam() *Team { + if t == nil { + return nil + } + return t.Team +} + +// GetDescription returns the Description field. +func (t *TeamChange) GetDescription() *TeamDescription { + if t == nil { + return nil + } + return t.Description +} + +// GetName returns the Name field. +func (t *TeamChange) GetName() *TeamName { + if t == nil { + return nil + } + return t.Name +} + +// GetPrivacy returns the Privacy field. +func (t *TeamChange) GetPrivacy() *TeamPrivacy { + if t == nil { + return nil + } + return t.Privacy +} + +// GetRepository returns the Repository field. +func (t *TeamChange) GetRepository() *TeamRepository { + if t == nil { + return nil + } + return t.Repository +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamDescription) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetAuthor returns the Author field. +func (t *TeamDiscussion) GetAuthor() *User { + if t == nil { + return nil + } + return t.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBody() string { + if t == nil || t.Body == nil { + return "" + } + return *t.Body +} + +// GetBodyHTML returns the BodyHTML field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBodyHTML() string { + if t == nil || t.BodyHTML == nil { + return "" + } + return *t.BodyHTML +} + +// GetBodyVersion returns the BodyVersion field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetBodyVersion() string { + if t == nil || t.BodyVersion == nil { + return "" + } + return *t.BodyVersion +} + +// GetCommentsCount returns the CommentsCount field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCommentsCount() int { + if t == nil || t.CommentsCount == nil { + return 0 + } + return *t.CommentsCount +} + +// GetCommentsURL returns the CommentsURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCommentsURL() string { + if t == nil || t.CommentsURL == nil { + return "" + } + return *t.CommentsURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetHTMLURL() string { + if t == nil || t.HTMLURL == nil { + return "" + } + return *t.HTMLURL +} + +// GetLastEditedAt returns the LastEditedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetLastEditedAt() Timestamp { + if t == nil || t.LastEditedAt == nil { + return Timestamp{} + } + return *t.LastEditedAt +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetNodeID() string { + if t == nil || t.NodeID == nil { + return "" + } + return *t.NodeID +} + +// GetNumber returns the Number field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetNumber() int { + if t == nil || t.Number == nil { + return 0 + } + return *t.Number +} + +// GetPinned returns the Pinned field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetPinned() bool { + if t == nil || t.Pinned == nil { + return false + } + return *t.Pinned +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetPrivate() bool { + if t == nil || t.Private == nil { + return false + } + return *t.Private +} + +// GetReactions returns the Reactions field. +func (t *TeamDiscussion) GetReactions() *Reactions { + if t == nil { + return nil + } + return t.Reactions +} + +// GetTeamURL returns the TeamURL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetTeamURL() string { + if t == nil || t.TeamURL == nil { + return "" + } + return *t.TeamURL +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetTitle() string { + if t == nil || t.Title == nil { + return "" + } + return *t.Title +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetUpdatedAt() Timestamp { + if t == nil || t.UpdatedAt == nil { + return Timestamp{} + } + return *t.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TeamDiscussion) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (t *TeamEvent) GetAction() string { + if t == nil || t.Action == nil { + return "" + } + return *t.Action +} + +// GetChanges returns the Changes field. +func (t *TeamEvent) GetChanges() *TeamChange { + if t == nil { + return nil + } + return t.Changes +} + +// GetInstallation returns the Installation field. +func (t *TeamEvent) GetInstallation() *Installation { + if t == nil { + return nil + } + return t.Installation +} + +// GetOrg returns the Org field. +func (t *TeamEvent) GetOrg() *Organization { + if t == nil { + return nil + } + return t.Org +} + +// GetRepo returns the Repo field. +func (t *TeamEvent) GetRepo() *Repository { + if t == nil { + return nil + } + return t.Repo +} + +// GetSender returns the Sender field. +func (t *TeamEvent) GetSender() *User { + if t == nil { + return nil + } + return t.Sender +} + +// GetTeam returns the Team field. +func (t *TeamEvent) GetTeam() *Team { + if t == nil { + return nil + } + return t.Team +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetLDAPDN() string { + if t == nil || t.LDAPDN == nil { + return "" + } + return *t.LDAPDN +} + +// GetMembersURL returns the MembersURL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetMembersURL() string { + if t == nil || t.MembersURL == nil { + return "" + } + return *t.MembersURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPrivacy returns the Privacy field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetPrivacy() string { + if t == nil || t.Privacy == nil { + return "" + } + return *t.Privacy +} + +// GetRepositoriesURL returns the RepositoriesURL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetRepositoriesURL() string { + if t == nil || t.RepositoriesURL == nil { + return "" + } + return *t.RepositoriesURL +} + +// GetSlug returns the Slug field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetSlug() string { + if t == nil || t.Slug == nil { + return "" + } + return *t.Slug +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TeamLDAPMapping) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamName) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetFrom returns the From field. +func (t *TeamPermissions) GetFrom() *TeamPermissionsFrom { + if t == nil { + return nil + } + return t.From +} + +// GetAdmin returns the Admin field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetAdmin() bool { + if t == nil || t.Admin == nil { + return false + } + return *t.Admin +} + +// GetPull returns the Pull field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetPull() bool { + if t == nil || t.Pull == nil { + return false + } + return *t.Pull +} + +// GetPush returns the Push field if it's non-nil, zero value otherwise. +func (t *TeamPermissionsFrom) GetPush() bool { + if t == nil || t.Push == nil { + return false + } + return *t.Push +} + +// GetFrom returns the From field if it's non-nil, zero value otherwise. +func (t *TeamPrivacy) GetFrom() string { + if t == nil || t.From == nil { + return "" + } + return *t.From +} + +// GetPermission returns the Permission field if it's non-nil, zero value otherwise. +func (t *TeamProjectOptions) GetPermission() string { + if t == nil || t.Permission == nil { + return "" + } + return *t.Permission +} + +// GetPermissions returns the Permissions field. +func (t *TeamRepository) GetPermissions() *TeamPermissions { + if t == nil { + return nil + } + return t.Permissions +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetIncludeAllBranches returns the IncludeAllBranches field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetIncludeAllBranches() bool { + if t == nil || t.IncludeAllBranches == nil { + return false + } + return *t.IncludeAllBranches +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetOwner returns the Owner field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetOwner() string { + if t == nil || t.Owner == nil { + return "" + } + return *t.Owner +} + +// GetPrivate returns the Private field if it's non-nil, zero value otherwise. +func (t *TemplateRepoRequest) GetPrivate() bool { + if t == nil || t.Private == nil { + return false + } + return *t.Private +} + +// GetFragment returns the Fragment field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetFragment() string { + if t == nil || t.Fragment == nil { + return "" + } + return *t.Fragment +} + +// GetObjectType returns the ObjectType field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetObjectType() string { + if t == nil || t.ObjectType == nil { + return "" + } + return *t.ObjectType +} + +// GetObjectURL returns the ObjectURL field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetObjectURL() string { + if t == nil || t.ObjectURL == nil { + return "" + } + return *t.ObjectURL +} + +// GetProperty returns the Property field if it's non-nil, zero value otherwise. +func (t *TextMatch) GetProperty() string { + if t == nil || t.Property == nil { + return "" + } + return *t.Property +} + +// GetActor returns the Actor field. +func (t *Timeline) GetActor() *User { + if t == nil { + return nil + } + return t.Actor +} + +// GetAssignee returns the Assignee field. +func (t *Timeline) GetAssignee() *User { + if t == nil { + return nil + } + return t.Assignee +} + +// GetAssigner returns the Assigner field. +func (t *Timeline) GetAssigner() *User { + if t == nil { + return nil + } + return t.Assigner +} + +// GetAuthor returns the Author field. +func (t *Timeline) GetAuthor() *CommitAuthor { + if t == nil { + return nil + } + return t.Author +} + +// GetBody returns the Body field if it's non-nil, zero value otherwise. +func (t *Timeline) GetBody() string { + if t == nil || t.Body == nil { + return "" + } + return *t.Body +} + +// GetCommitID returns the CommitID field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCommitID() string { + if t == nil || t.CommitID == nil { + return "" + } + return *t.CommitID +} + +// GetCommitter returns the Committer field. +func (t *Timeline) GetCommitter() *CommitAuthor { + if t == nil { + return nil + } + return t.Committer +} + +// GetCommitURL returns the CommitURL field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCommitURL() string { + if t == nil || t.CommitURL == nil { + return "" + } + return *t.CommitURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *Timeline) GetCreatedAt() time.Time { + if t == nil || t.CreatedAt == nil { + return time.Time{} + } + return *t.CreatedAt +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (t *Timeline) GetEvent() string { + if t == nil || t.Event == nil { + return "" + } + return *t.Event +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (t *Timeline) GetID() int64 { + if t == nil || t.ID == nil { + return 0 + } + return *t.ID +} + +// GetLabel returns the Label field. +func (t *Timeline) GetLabel() *Label { + if t == nil { + return nil + } + return t.Label +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (t *Timeline) GetMessage() string { + if t == nil || t.Message == nil { + return "" + } + return *t.Message +} + +// GetMilestone returns the Milestone field. +func (t *Timeline) GetMilestone() *Milestone { + if t == nil { + return nil + } + return t.Milestone +} + +// GetProjectCard returns the ProjectCard field. +func (t *Timeline) GetProjectCard() *ProjectCard { + if t == nil { + return nil + } + return t.ProjectCard +} + +// GetRename returns the Rename field. +func (t *Timeline) GetRename() *Rename { + if t == nil { + return nil + } + return t.Rename +} + +// GetRequester returns the Requester field. +func (t *Timeline) GetRequester() *User { + if t == nil { + return nil + } + return t.Requester +} + +// GetReviewer returns the Reviewer field. +func (t *Timeline) GetReviewer() *User { + if t == nil { + return nil + } + return t.Reviewer +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Timeline) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetSource returns the Source field. +func (t *Timeline) GetSource() *Source { + if t == nil { + return nil + } + return t.Source +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (t *Timeline) GetState() string { + if t == nil || t.State == nil { + return "" + } + return *t.State +} + +// GetSubmittedAt returns the SubmittedAt field if it's non-nil, zero value otherwise. +func (t *Timeline) GetSubmittedAt() time.Time { + if t == nil || t.SubmittedAt == nil { + return time.Time{} + } + return *t.SubmittedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *Timeline) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetUser returns the User field. +func (t *Timeline) GetUser() *User { + if t == nil { + return nil + } + return t.User +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (t *Tool) GetGUID() string { + if t == nil || t.GUID == nil { + return "" + } + return *t.GUID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *Tool) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetVersion returns the Version field if it's non-nil, zero value otherwise. +func (t *Tool) GetVersion() string { + if t == nil || t.Version == nil { + return "" + } + return *t.Version +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCreatedAt() Timestamp { + if t == nil || t.CreatedAt == nil { + return Timestamp{} + } + return *t.CreatedAt +} + +// GetCreatedBy returns the CreatedBy field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCreatedBy() string { + if t == nil || t.CreatedBy == nil { + return "" + } + return *t.CreatedBy +} + +// GetCurated returns the Curated field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetCurated() bool { + if t == nil || t.Curated == nil { + return false + } + return *t.Curated +} + +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetDescription() string { + if t == nil || t.Description == nil { + return "" + } + return *t.Description +} + +// GetDisplayName returns the DisplayName field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetDisplayName() string { + if t == nil || t.DisplayName == nil { + return "" + } + return *t.DisplayName +} + +// GetFeatured returns the Featured field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetFeatured() bool { + if t == nil || t.Featured == nil { + return false + } + return *t.Featured +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetName() string { + if t == nil || t.Name == nil { + return "" + } + return *t.Name +} + +// GetScore returns the Score field. +func (t *TopicResult) GetScore() *float64 { + if t == nil { + return nil + } + return t.Score +} + +// GetShortDescription returns the ShortDescription field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetShortDescription() string { + if t == nil || t.ShortDescription == nil { + return "" + } + return *t.ShortDescription +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (t *TopicResult) GetUpdatedAt() string { + if t == nil || t.UpdatedAt == nil { + return "" + } + return *t.UpdatedAt +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (t *TopicsSearchResult) GetIncompleteResults() bool { + if t == nil || t.IncompleteResults == nil { + return false + } + return *t.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (t *TopicsSearchResult) GetTotal() int { + if t == nil || t.Total == nil { + return 0 + } + return *t.Total +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficClones) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficClones) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetTimestamp returns the Timestamp field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetTimestamp() Timestamp { + if t == nil || t.Timestamp == nil { + return Timestamp{} + } + return *t.Timestamp +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficData) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetPath() string { + if t == nil || t.Path == nil { + return "" + } + return *t.Path +} + +// GetTitle returns the Title field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetTitle() string { + if t == nil || t.Title == nil { + return "" + } + return *t.Title +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficPath) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetReferrer returns the Referrer field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetReferrer() string { + if t == nil || t.Referrer == nil { + return "" + } + return *t.Referrer +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficReferrer) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetCount returns the Count field if it's non-nil, zero value otherwise. +func (t *TrafficViews) GetCount() int { + if t == nil || t.Count == nil { + return 0 + } + return *t.Count +} + +// GetUniques returns the Uniques field if it's non-nil, zero value otherwise. +func (t *TrafficViews) GetUniques() int { + if t == nil || t.Uniques == nil { + return 0 + } + return *t.Uniques +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *Tree) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetTruncated returns the Truncated field if it's non-nil, zero value otherwise. +func (t *Tree) GetTruncated() bool { + if t == nil || t.Truncated == nil { + return false + } + return *t.Truncated +} + +// GetContent returns the Content field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetContent() string { + if t == nil || t.Content == nil { + return "" + } + return *t.Content +} + +// GetMode returns the Mode field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetMode() string { + if t == nil || t.Mode == nil { + return "" + } + return *t.Mode +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetPath() string { + if t == nil || t.Path == nil { + return "" + } + return *t.Path +} + +// GetSHA returns the SHA field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetSHA() string { + if t == nil || t.SHA == nil { + return "" + } + return *t.SHA +} + +// GetSize returns the Size field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetSize() int { + if t == nil || t.Size == nil { + return 0 + } + return *t.Size +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetType() string { + if t == nil || t.Type == nil { + return "" + } + return *t.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (t *TreeEntry) GetURL() string { + if t == nil || t.URL == nil { + return "" + } + return *t.URL +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (u *UpdateAttributeForSCIMUserOperations) GetPath() string { + if u == nil || u.Path == nil { + return "" + } + return *u.Path +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetCompletedAt() Timestamp { + if u == nil || u.CompletedAt == nil { + return Timestamp{} + } + return *u.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetConclusion() string { + if u == nil || u.Conclusion == nil { + return "" + } + return *u.Conclusion +} + +// GetDetailsURL returns the DetailsURL field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetDetailsURL() string { + if u == nil || u.DetailsURL == nil { + return "" + } + return *u.DetailsURL +} + +// GetExternalID returns the ExternalID field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetExternalID() string { + if u == nil || u.ExternalID == nil { + return "" + } + return *u.ExternalID +} + +// GetOutput returns the Output field. +func (u *UpdateCheckRunOptions) GetOutput() *CheckRunOutput { + if u == nil { + return nil + } + return u.Output +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (u *UpdateCheckRunOptions) GetStatus() string { + if u == nil || u.Status == nil { + return "" + } + return *u.Status +} + +// GetAllowsPublicRepositories returns the AllowsPublicRepositories field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetAllowsPublicRepositories() bool { + if u == nil || u.AllowsPublicRepositories == nil { + return false + } + return *u.AllowsPublicRepositories +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (u *UpdateRunnerGroupRequest) GetVisibility() string { + if u == nil || u.Visibility == nil { + return "" + } + return *u.Visibility +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (u *User) GetAvatarURL() string { + if u == nil || u.AvatarURL == nil { + return "" + } + return *u.AvatarURL +} + +// GetBio returns the Bio field if it's non-nil, zero value otherwise. +func (u *User) GetBio() string { + if u == nil || u.Bio == nil { + return "" + } + return *u.Bio +} + +// GetBlog returns the Blog field if it's non-nil, zero value otherwise. +func (u *User) GetBlog() string { + if u == nil || u.Blog == nil { + return "" + } + return *u.Blog +} + +// GetCollaborators returns the Collaborators field if it's non-nil, zero value otherwise. +func (u *User) GetCollaborators() int { + if u == nil || u.Collaborators == nil { + return 0 + } + return *u.Collaborators +} + +// GetCompany returns the Company field if it's non-nil, zero value otherwise. +func (u *User) GetCompany() string { + if u == nil || u.Company == nil { + return "" + } + return *u.Company +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *User) GetCreatedAt() Timestamp { + if u == nil || u.CreatedAt == nil { + return Timestamp{} + } + return *u.CreatedAt +} + +// GetDiskUsage returns the DiskUsage field if it's non-nil, zero value otherwise. +func (u *User) GetDiskUsage() int { + if u == nil || u.DiskUsage == nil { + return 0 + } + return *u.DiskUsage +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (u *User) GetEmail() string { + if u == nil || u.Email == nil { + return "" + } + return *u.Email +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (u *User) GetEventsURL() string { + if u == nil || u.EventsURL == nil { + return "" + } + return *u.EventsURL +} + +// GetFollowers returns the Followers field if it's non-nil, zero value otherwise. +func (u *User) GetFollowers() int { + if u == nil || u.Followers == nil { + return 0 + } + return *u.Followers +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (u *User) GetFollowersURL() string { + if u == nil || u.FollowersURL == nil { + return "" + } + return *u.FollowersURL +} + +// GetFollowing returns the Following field if it's non-nil, zero value otherwise. +func (u *User) GetFollowing() int { + if u == nil || u.Following == nil { + return 0 + } + return *u.Following +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (u *User) GetFollowingURL() string { + if u == nil || u.FollowingURL == nil { + return "" + } + return *u.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (u *User) GetGistsURL() string { + if u == nil || u.GistsURL == nil { + return "" + } + return *u.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (u *User) GetGravatarID() string { + if u == nil || u.GravatarID == nil { + return "" + } + return *u.GravatarID +} + +// GetHireable returns the Hireable field if it's non-nil, zero value otherwise. +func (u *User) GetHireable() bool { + if u == nil || u.Hireable == nil { + return false + } + return *u.Hireable +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (u *User) GetHTMLURL() string { + if u == nil || u.HTMLURL == nil { + return "" + } + return *u.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *User) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLdapDn returns the LdapDn field if it's non-nil, zero value otherwise. +func (u *User) GetLdapDn() string { + if u == nil || u.LdapDn == nil { + return "" + } + return *u.LdapDn +} + +// GetLocation returns the Location field if it's non-nil, zero value otherwise. +func (u *User) GetLocation() string { + if u == nil || u.Location == nil { + return "" + } + return *u.Location +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (u *User) GetLogin() string { + if u == nil || u.Login == nil { + return "" + } + return *u.Login +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (u *User) GetName() string { + if u == nil || u.Name == nil { + return "" + } + return *u.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (u *User) GetNodeID() string { + if u == nil || u.NodeID == nil { + return "" + } + return *u.NodeID +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (u *User) GetOrganizationsURL() string { + if u == nil || u.OrganizationsURL == nil { + return "" + } + return *u.OrganizationsURL +} + +// GetOwnedPrivateRepos returns the OwnedPrivateRepos field if it's non-nil, zero value otherwise. +func (u *User) GetOwnedPrivateRepos() int { + if u == nil || u.OwnedPrivateRepos == nil { + return 0 + } + return *u.OwnedPrivateRepos +} + +// GetPermissions returns the Permissions map if it's non-nil, an empty map otherwise. +func (u *User) GetPermissions() map[string]bool { + if u == nil || u.Permissions == nil { + return map[string]bool{} + } + return u.Permissions +} + +// GetPlan returns the Plan field. +func (u *User) GetPlan() *Plan { + if u == nil { + return nil + } + return u.Plan +} + +// GetPrivateGists returns the PrivateGists field if it's non-nil, zero value otherwise. +func (u *User) GetPrivateGists() int { + if u == nil || u.PrivateGists == nil { + return 0 + } + return *u.PrivateGists +} + +// GetPublicGists returns the PublicGists field if it's non-nil, zero value otherwise. +func (u *User) GetPublicGists() int { + if u == nil || u.PublicGists == nil { + return 0 + } + return *u.PublicGists +} + +// GetPublicRepos returns the PublicRepos field if it's non-nil, zero value otherwise. +func (u *User) GetPublicRepos() int { + if u == nil || u.PublicRepos == nil { + return 0 + } + return *u.PublicRepos +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (u *User) GetReceivedEventsURL() string { + if u == nil || u.ReceivedEventsURL == nil { + return "" + } + return *u.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (u *User) GetReposURL() string { + if u == nil || u.ReposURL == nil { + return "" + } + return *u.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (u *User) GetSiteAdmin() bool { + if u == nil || u.SiteAdmin == nil { + return false + } + return *u.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (u *User) GetStarredURL() string { + if u == nil || u.StarredURL == nil { + return "" + } + return *u.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (u *User) GetSubscriptionsURL() string { + if u == nil || u.SubscriptionsURL == nil { + return "" + } + return *u.SubscriptionsURL +} + +// GetSuspendedAt returns the SuspendedAt field if it's non-nil, zero value otherwise. +func (u *User) GetSuspendedAt() Timestamp { + if u == nil || u.SuspendedAt == nil { + return Timestamp{} + } + return *u.SuspendedAt +} + +// GetTotalPrivateRepos returns the TotalPrivateRepos field if it's non-nil, zero value otherwise. +func (u *User) GetTotalPrivateRepos() int { + if u == nil || u.TotalPrivateRepos == nil { + return 0 + } + return *u.TotalPrivateRepos +} + +// GetTwitterUsername returns the TwitterUsername field if it's non-nil, zero value otherwise. +func (u *User) GetTwitterUsername() string { + if u == nil || u.TwitterUsername == nil { + return "" + } + return *u.TwitterUsername +} + +// GetTwoFactorAuthentication returns the TwoFactorAuthentication field if it's non-nil, zero value otherwise. +func (u *User) GetTwoFactorAuthentication() bool { + if u == nil || u.TwoFactorAuthentication == nil { + return false + } + return *u.TwoFactorAuthentication +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *User) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *User) GetUpdatedAt() Timestamp { + if u == nil || u.UpdatedAt == nil { + return Timestamp{} + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *User) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetApp returns the App field. +func (u *UserAuthorization) GetApp() *OAuthAPP { + if u == nil { + return nil + } + return u.App +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetCreatedAt() Timestamp { + if u == nil || u.CreatedAt == nil { + return Timestamp{} + } + return *u.CreatedAt +} + +// GetFingerprint returns the Fingerprint field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetFingerprint() string { + if u == nil || u.Fingerprint == nil { + return "" + } + return *u.Fingerprint +} + +// GetHashedToken returns the HashedToken field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetHashedToken() string { + if u == nil || u.HashedToken == nil { + return "" + } + return *u.HashedToken +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetNote returns the Note field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetNote() string { + if u == nil || u.Note == nil { + return "" + } + return *u.Note +} + +// GetNoteURL returns the NoteURL field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetNoteURL() string { + if u == nil || u.NoteURL == nil { + return "" + } + return *u.NoteURL +} + +// GetToken returns the Token field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetToken() string { + if u == nil || u.Token == nil { + return "" + } + return *u.Token +} + +// GetTokenLastEight returns the TokenLastEight field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetTokenLastEight() string { + if u == nil || u.TokenLastEight == nil { + return "" + } + return *u.TokenLastEight +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetUpdatedAt() Timestamp { + if u == nil || u.UpdatedAt == nil { + return Timestamp{} + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserAuthorization) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetMessage returns the Message field if it's non-nil, zero value otherwise. +func (u *UserContext) GetMessage() string { + if u == nil || u.Message == nil { + return "" + } + return *u.Message +} + +// GetOcticon returns the Octicon field if it's non-nil, zero value otherwise. +func (u *UserContext) GetOcticon() string { + if u == nil || u.Octicon == nil { + return "" + } + return *u.Octicon +} + +// GetEmail returns the Email field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetEmail() string { + if u == nil || u.Email == nil { + return "" + } + return *u.Email +} + +// GetPrimary returns the Primary field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetPrimary() bool { + if u == nil || u.Primary == nil { + return false + } + return *u.Primary +} + +// GetVerified returns the Verified field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetVerified() bool { + if u == nil || u.Verified == nil { + return false + } + return *u.Verified +} + +// GetVisibility returns the Visibility field if it's non-nil, zero value otherwise. +func (u *UserEmail) GetVisibility() string { + if u == nil || u.Visibility == nil { + return "" + } + return *u.Visibility +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (u *UserEvent) GetAction() string { + if u == nil || u.Action == nil { + return "" + } + return *u.Action +} + +// GetEnterprise returns the Enterprise field. +func (u *UserEvent) GetEnterprise() *Enterprise { + if u == nil { + return nil + } + return u.Enterprise +} + +// GetInstallation returns the Installation field. +func (u *UserEvent) GetInstallation() *Installation { + if u == nil { + return nil + } + return u.Installation +} + +// GetSender returns the Sender field. +func (u *UserEvent) GetSender() *User { + if u == nil { + return nil + } + return u.Sender +} + +// GetUser returns the User field. +func (u *UserEvent) GetUser() *User { + if u == nil { + return nil + } + return u.User +} + +// GetAvatarURL returns the AvatarURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetAvatarURL() string { + if u == nil || u.AvatarURL == nil { + return "" + } + return *u.AvatarURL +} + +// GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetEventsURL() string { + if u == nil || u.EventsURL == nil { + return "" + } + return *u.EventsURL +} + +// GetFollowersURL returns the FollowersURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetFollowersURL() string { + if u == nil || u.FollowersURL == nil { + return "" + } + return *u.FollowersURL +} + +// GetFollowingURL returns the FollowingURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetFollowingURL() string { + if u == nil || u.FollowingURL == nil { + return "" + } + return *u.FollowingURL +} + +// GetGistsURL returns the GistsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetGistsURL() string { + if u == nil || u.GistsURL == nil { + return "" + } + return *u.GistsURL +} + +// GetGravatarID returns the GravatarID field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetGravatarID() string { + if u == nil || u.GravatarID == nil { + return "" + } + return *u.GravatarID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLDAPDN returns the LDAPDN field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetLDAPDN() string { + if u == nil || u.LDAPDN == nil { + return "" + } + return *u.LDAPDN +} + +// GetLogin returns the Login field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetLogin() string { + if u == nil || u.Login == nil { + return "" + } + return *u.Login +} + +// GetOrganizationsURL returns the OrganizationsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetOrganizationsURL() string { + if u == nil || u.OrganizationsURL == nil { + return "" + } + return *u.OrganizationsURL +} + +// GetReceivedEventsURL returns the ReceivedEventsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetReceivedEventsURL() string { + if u == nil || u.ReceivedEventsURL == nil { + return "" + } + return *u.ReceivedEventsURL +} + +// GetReposURL returns the ReposURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetReposURL() string { + if u == nil || u.ReposURL == nil { + return "" + } + return *u.ReposURL +} + +// GetSiteAdmin returns the SiteAdmin field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetSiteAdmin() bool { + if u == nil || u.SiteAdmin == nil { + return false + } + return *u.SiteAdmin +} + +// GetStarredURL returns the StarredURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetStarredURL() string { + if u == nil || u.StarredURL == nil { + return "" + } + return *u.StarredURL +} + +// GetSubscriptionsURL returns the SubscriptionsURL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetSubscriptionsURL() string { + if u == nil || u.SubscriptionsURL == nil { + return "" + } + return *u.SubscriptionsURL +} + +// GetType returns the Type field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetType() string { + if u == nil || u.Type == nil { + return "" + } + return *u.Type +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserLDAPMapping) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetCreatedAt() string { + if u == nil || u.CreatedAt == nil { + return "" + } + return *u.CreatedAt +} + +// GetExcludeAttachments returns the ExcludeAttachments field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetExcludeAttachments() bool { + if u == nil || u.ExcludeAttachments == nil { + return false + } + return *u.ExcludeAttachments +} + +// GetGUID returns the GUID field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetGUID() string { + if u == nil || u.GUID == nil { + return "" + } + return *u.GUID +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetID() int64 { + if u == nil || u.ID == nil { + return 0 + } + return *u.ID +} + +// GetLockRepositories returns the LockRepositories field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetLockRepositories() bool { + if u == nil || u.LockRepositories == nil { + return false + } + return *u.LockRepositories +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetState() string { + if u == nil || u.State == nil { + return "" + } + return *u.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetUpdatedAt() string { + if u == nil || u.UpdatedAt == nil { + return "" + } + return *u.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (u *UserMigration) GetURL() string { + if u == nil || u.URL == nil { + return "" + } + return *u.URL +} + +// GetIncompleteResults returns the IncompleteResults field if it's non-nil, zero value otherwise. +func (u *UsersSearchResult) GetIncompleteResults() bool { + if u == nil || u.IncompleteResults == nil { + return false + } + return *u.IncompleteResults +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (u *UsersSearchResult) GetTotal() int { + if u == nil || u.Total == nil { + return 0 + } + return *u.Total +} + +// GetAdminUsers returns the AdminUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetAdminUsers() int { + if u == nil || u.AdminUsers == nil { + return 0 + } + return *u.AdminUsers +} + +// GetSuspendedUsers returns the SuspendedUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetSuspendedUsers() int { + if u == nil || u.SuspendedUsers == nil { + return 0 + } + return *u.SuspendedUsers +} + +// GetTotalUsers returns the TotalUsers field if it's non-nil, zero value otherwise. +func (u *UserStats) GetTotalUsers() int { + if u == nil || u.TotalUsers == nil { + return 0 + } + return *u.TotalUsers +} + +// GetReason returns the Reason field if it's non-nil, zero value otherwise. +func (u *UserSuspendOptions) GetReason() string { + if u == nil || u.Reason == nil { + return "" + } + return *u.Reason +} + +// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise. +func (v *VulnerabilityPackage) GetEcosystem() string { + if v == nil || v.Ecosystem == nil { + return "" + } + return *v.Ecosystem +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (v *VulnerabilityPackage) GetName() string { + if v == nil || v.Name == nil { + return "" + } + return *v.Name +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WatchEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetInstallation returns the Installation field. +func (w *WatchEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetRepo returns the Repo field. +func (w *WatchEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WatchEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetTotal returns the Total field if it's non-nil, zero value otherwise. +func (w *WeeklyCommitActivity) GetTotal() int { + if w == nil || w.Total == nil { + return 0 + } + return *w.Total +} + +// GetWeek returns the Week field if it's non-nil, zero value otherwise. +func (w *WeeklyCommitActivity) GetWeek() Timestamp { + if w == nil || w.Week == nil { + return Timestamp{} + } + return *w.Week +} + +// GetAdditions returns the Additions field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetAdditions() int { + if w == nil || w.Additions == nil { + return 0 + } + return *w.Additions +} + +// GetCommits returns the Commits field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetCommits() int { + if w == nil || w.Commits == nil { + return 0 + } + return *w.Commits +} + +// GetDeletions returns the Deletions field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetDeletions() int { + if w == nil || w.Deletions == nil { + return 0 + } + return *w.Deletions +} + +// GetWeek returns the Week field if it's non-nil, zero value otherwise. +func (w *WeeklyStats) GetWeek() Timestamp { + if w == nil || w.Week == nil { + return Timestamp{} + } + return *w.Week +} + +// GetBadgeURL returns the BadgeURL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetBadgeURL() string { + if w == nil || w.BadgeURL == nil { + return "" + } + return *w.BadgeURL +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *Workflow) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *Workflow) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *Workflow) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *Workflow) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetPath returns the Path field if it's non-nil, zero value otherwise. +func (w *Workflow) GetPath() string { + if w == nil || w.Path == nil { + return "" + } + return *w.Path +} + +// GetState returns the State field if it's non-nil, zero value otherwise. +func (w *Workflow) GetState() string { + if w == nil || w.State == nil { + return "" + } + return *w.State +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (w *Workflow) GetUpdatedAt() Timestamp { + if w == nil || w.UpdatedAt == nil { + return Timestamp{} + } + return *w.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *Workflow) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetTotalMS returns the TotalMS field if it's non-nil, zero value otherwise. +func (w *WorkflowBill) GetTotalMS() int64 { + if w == nil || w.TotalMS == nil { + return 0 + } + return *w.TotalMS +} + +// GetInstallation returns the Installation field. +func (w *WorkflowDispatchEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowDispatchEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRef returns the Ref field if it's non-nil, zero value otherwise. +func (w *WorkflowDispatchEvent) GetRef() string { + if w == nil || w.Ref == nil { + return "" + } + return *w.Ref +} + +// GetRepo returns the Repo field. +func (w *WorkflowDispatchEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowDispatchEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflow returns the Workflow field if it's non-nil, zero value otherwise. +func (w *WorkflowDispatchEvent) GetWorkflow() string { + if w == nil || w.Workflow == nil { + return "" + } + return *w.Workflow +} + +// GetMacOS returns the MacOS field. +func (w *WorkflowEnvironment) GetMacOS() *WorkflowBill { + if w == nil { + return nil + } + return w.MacOS +} + +// GetUbuntu returns the Ubuntu field. +func (w *WorkflowEnvironment) GetUbuntu() *WorkflowBill { + if w == nil { + return nil + } + return w.Ubuntu +} + +// GetWindows returns the Windows field. +func (w *WorkflowEnvironment) GetWindows() *WorkflowBill { + if w == nil { + return nil + } + return w.Windows +} + +// GetCheckRunURL returns the CheckRunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetCheckRunURL() string { + if w == nil || w.CheckRunURL == nil { + return "" + } + return *w.CheckRunURL +} + +// GetCompletedAt returns the CompletedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetCompletedAt() Timestamp { + if w == nil || w.CompletedAt == nil { + return Timestamp{} + } + return *w.CompletedAt +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetConclusion() string { + if w == nil || w.Conclusion == nil { + return "" + } + return *w.Conclusion +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetHeadSHA() string { + if w == nil || w.HeadSHA == nil { + return "" + } + return *w.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetRunID returns the RunID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunID() int64 { + if w == nil || w.RunID == nil { + return 0 + } + return *w.RunID +} + +// GetRunnerGroupID returns the RunnerGroupID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerGroupID() int64 { + if w == nil || w.RunnerGroupID == nil { + return 0 + } + return *w.RunnerGroupID +} + +// GetRunnerGroupName returns the RunnerGroupName field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerGroupName() string { + if w == nil || w.RunnerGroupName == nil { + return "" + } + return *w.RunnerGroupName +} + +// GetRunnerID returns the RunnerID field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerID() int64 { + if w == nil || w.RunnerID == nil { + return 0 + } + return *w.RunnerID +} + +// GetRunnerName returns the RunnerName field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunnerName() string { + if w == nil || w.RunnerName == nil { + return "" + } + return *w.RunnerName +} + +// GetRunURL returns the RunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetRunURL() string { + if w == nil || w.RunURL == nil { + return "" + } + return *w.RunURL +} + +// GetStartedAt returns the StartedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetStartedAt() Timestamp { + if w == nil || w.StartedAt == nil { + return Timestamp{} + } + return *w.StartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetStatus() string { + if w == nil || w.Status == nil { + return "" + } + return *w.Status +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *WorkflowJob) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WorkflowJobEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetInstallation returns the Installation field. +func (w *WorkflowJobEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowJobEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRepo returns the Repo field. +func (w *WorkflowJobEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowJobEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflowJob returns the WorkflowJob field. +func (w *WorkflowJobEvent) GetWorkflowJob() *WorkflowJob { + if w == nil { + return nil + } + return w.WorkflowJob +} + +// GetArtifactsURL returns the ArtifactsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetArtifactsURL() string { + if w == nil || w.ArtifactsURL == nil { + return "" + } + return *w.ArtifactsURL +} + +// GetCancelURL returns the CancelURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCancelURL() string { + if w == nil || w.CancelURL == nil { + return "" + } + return *w.CancelURL +} + +// GetCheckSuiteID returns the CheckSuiteID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteID() int64 { + if w == nil || w.CheckSuiteID == nil { + return 0 + } + return *w.CheckSuiteID +} + +// GetCheckSuiteNodeID returns the CheckSuiteNodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteNodeID() string { + if w == nil || w.CheckSuiteNodeID == nil { + return "" + } + return *w.CheckSuiteNodeID +} + +// GetCheckSuiteURL returns the CheckSuiteURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCheckSuiteURL() string { + if w == nil || w.CheckSuiteURL == nil { + return "" + } + return *w.CheckSuiteURL +} + +// GetConclusion returns the Conclusion field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetConclusion() string { + if w == nil || w.Conclusion == nil { + return "" + } + return *w.Conclusion +} + +// GetCreatedAt returns the CreatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetCreatedAt() Timestamp { + if w == nil || w.CreatedAt == nil { + return Timestamp{} + } + return *w.CreatedAt +} + +// GetEvent returns the Event field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetEvent() string { + if w == nil || w.Event == nil { + return "" + } + return *w.Event +} + +// GetHeadBranch returns the HeadBranch field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHeadBranch() string { + if w == nil || w.HeadBranch == nil { + return "" + } + return *w.HeadBranch +} + +// GetHeadCommit returns the HeadCommit field. +func (w *WorkflowRun) GetHeadCommit() *HeadCommit { + if w == nil { + return nil + } + return w.HeadCommit +} + +// GetHeadRepository returns the HeadRepository field. +func (w *WorkflowRun) GetHeadRepository() *Repository { + if w == nil { + return nil + } + return w.HeadRepository +} + +// GetHeadSHA returns the HeadSHA field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHeadSHA() string { + if w == nil || w.HeadSHA == nil { + return "" + } + return *w.HeadSHA +} + +// GetHTMLURL returns the HTMLURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetHTMLURL() string { + if w == nil || w.HTMLURL == nil { + return "" + } + return *w.HTMLURL +} + +// GetID returns the ID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetID() int64 { + if w == nil || w.ID == nil { + return 0 + } + return *w.ID +} + +// GetJobsURL returns the JobsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetJobsURL() string { + if w == nil || w.JobsURL == nil { + return "" + } + return *w.JobsURL +} + +// GetLogsURL returns the LogsURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetLogsURL() string { + if w == nil || w.LogsURL == nil { + return "" + } + return *w.LogsURL +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetName() string { + if w == nil || w.Name == nil { + return "" + } + return *w.Name +} + +// GetNodeID returns the NodeID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetNodeID() string { + if w == nil || w.NodeID == nil { + return "" + } + return *w.NodeID +} + +// GetPreviousAttemptURL returns the PreviousAttemptURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetPreviousAttemptURL() string { + if w == nil || w.PreviousAttemptURL == nil { + return "" + } + return *w.PreviousAttemptURL +} + +// GetRepository returns the Repository field. +func (w *WorkflowRun) GetRepository() *Repository { + if w == nil { + return nil + } + return w.Repository +} + +// GetRerunURL returns the RerunURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRerunURL() string { + if w == nil || w.RerunURL == nil { + return "" + } + return *w.RerunURL +} + +// GetRunAttempt returns the RunAttempt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunAttempt() int { + if w == nil || w.RunAttempt == nil { + return 0 + } + return *w.RunAttempt +} + +// GetRunNumber returns the RunNumber field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunNumber() int { + if w == nil || w.RunNumber == nil { + return 0 + } + return *w.RunNumber +} + +// GetRunStartedAt returns the RunStartedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetRunStartedAt() Timestamp { + if w == nil || w.RunStartedAt == nil { + return Timestamp{} + } + return *w.RunStartedAt +} + +// GetStatus returns the Status field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetStatus() string { + if w == nil || w.Status == nil { + return "" + } + return *w.Status +} + +// GetUpdatedAt returns the UpdatedAt field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetUpdatedAt() Timestamp { + if w == nil || w.UpdatedAt == nil { + return Timestamp{} + } + return *w.UpdatedAt +} + +// GetURL returns the URL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetURL() string { + if w == nil || w.URL == nil { + return "" + } + return *w.URL +} + +// GetWorkflowID returns the WorkflowID field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetWorkflowID() int64 { + if w == nil || w.WorkflowID == nil { + return 0 + } + return *w.WorkflowID +} + +// GetWorkflowURL returns the WorkflowURL field if it's non-nil, zero value otherwise. +func (w *WorkflowRun) GetWorkflowURL() string { + if w == nil || w.WorkflowURL == nil { + return "" + } + return *w.WorkflowURL +} + +// GetExcludePullRequests returns the ExcludePullRequests field if it's non-nil, zero value otherwise. +func (w *WorkflowRunAttemptOptions) GetExcludePullRequests() bool { + if w == nil || w.ExcludePullRequests == nil { + return false + } + return *w.ExcludePullRequests +} + +// GetJobs returns the Jobs field if it's non-nil, zero value otherwise. +func (w *WorkflowRunBill) GetJobs() int { + if w == nil || w.Jobs == nil { + return 0 + } + return *w.Jobs +} + +// GetTotalMS returns the TotalMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunBill) GetTotalMS() int64 { + if w == nil || w.TotalMS == nil { + return 0 + } + return *w.TotalMS +} + +// GetMacOS returns the MacOS field. +func (w *WorkflowRunEnvironment) GetMacOS() *WorkflowRunBill { + if w == nil { + return nil + } + return w.MacOS +} + +// GetUbuntu returns the Ubuntu field. +func (w *WorkflowRunEnvironment) GetUbuntu() *WorkflowRunBill { + if w == nil { + return nil + } + return w.Ubuntu +} + +// GetWindows returns the Windows field. +func (w *WorkflowRunEnvironment) GetWindows() *WorkflowRunBill { + if w == nil { + return nil + } + return w.Windows +} + +// GetAction returns the Action field if it's non-nil, zero value otherwise. +func (w *WorkflowRunEvent) GetAction() string { + if w == nil || w.Action == nil { + return "" + } + return *w.Action +} + +// GetInstallation returns the Installation field. +func (w *WorkflowRunEvent) GetInstallation() *Installation { + if w == nil { + return nil + } + return w.Installation +} + +// GetOrg returns the Org field. +func (w *WorkflowRunEvent) GetOrg() *Organization { + if w == nil { + return nil + } + return w.Org +} + +// GetRepo returns the Repo field. +func (w *WorkflowRunEvent) GetRepo() *Repository { + if w == nil { + return nil + } + return w.Repo +} + +// GetSender returns the Sender field. +func (w *WorkflowRunEvent) GetSender() *User { + if w == nil { + return nil + } + return w.Sender +} + +// GetWorkflow returns the Workflow field. +func (w *WorkflowRunEvent) GetWorkflow() *Workflow { + if w == nil { + return nil + } + return w.Workflow +} + +// GetWorkflowRun returns the WorkflowRun field. +func (w *WorkflowRunEvent) GetWorkflowRun() *WorkflowRun { + if w == nil { + return nil + } + return w.WorkflowRun +} + +// GetDurationMS returns the DurationMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunJobRun) GetDurationMS() int64 { + if w == nil || w.DurationMS == nil { + return 0 + } + return *w.DurationMS +} + +// GetJobID returns the JobID field if it's non-nil, zero value otherwise. +func (w *WorkflowRunJobRun) GetJobID() int { + if w == nil || w.JobID == nil { + return 0 + } + return *w.JobID +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (w *WorkflowRuns) GetTotalCount() int { + if w == nil || w.TotalCount == nil { + return 0 + } + return *w.TotalCount +} + +// GetBillable returns the Billable field. +func (w *WorkflowRunUsage) GetBillable() *WorkflowRunEnvironment { + if w == nil { + return nil + } + return w.Billable +} + +// GetRunDurationMS returns the RunDurationMS field if it's non-nil, zero value otherwise. +func (w *WorkflowRunUsage) GetRunDurationMS() int64 { + if w == nil || w.RunDurationMS == nil { + return 0 + } + return *w.RunDurationMS +} + +// GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise. +func (w *Workflows) GetTotalCount() int { + if w == nil || w.TotalCount == nil { + return 0 + } + return *w.TotalCount +} + +// GetBillable returns the Billable field. +func (w *WorkflowUsage) GetBillable() *WorkflowEnvironment { + if w == nil { + return nil + } + return w.Billable +} diff --git a/vendor/github.com/google/go-github/v45/github/github.go b/vendor/github.com/google/go-github/v45/github/github.go new file mode 100644 index 0000000000..08b7db8e55 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/github.go @@ -0,0 +1,1366 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen-accessors.go +//go:generate go run gen-stringify-test.go + +package github + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "reflect" + "strconv" + "strings" + "sync" + "time" + + "github.com/google/go-querystring/query" +) + +const ( + defaultBaseURL = "https://api.github.com/" + uploadBaseURL = "https://uploads.github.com/" + userAgent = "go-github" + + headerRateLimit = "X-RateLimit-Limit" + headerRateRemaining = "X-RateLimit-Remaining" + headerRateReset = "X-RateLimit-Reset" + headerOTP = "X-GitHub-OTP" + + headerTokenExpiration = "GitHub-Authentication-Token-Expiration" + + mediaTypeV3 = "application/vnd.github.v3+json" + defaultMediaType = "application/octet-stream" + mediaTypeV3SHA = "application/vnd.github.v3.sha" + mediaTypeV3Diff = "application/vnd.github.v3.diff" + mediaTypeV3Patch = "application/vnd.github.v3.patch" + mediaTypeOrgPermissionRepo = "application/vnd.github.v3.repository+json" + mediaTypeIssueImportAPI = "application/vnd.github.golden-comet-preview+json" + + // Media Type values to access preview APIs + // These media types will be added to the API request as headers + // and used to enable particular features on GitHub API that are still in preview. + // After some time, specific media types will be promoted (to a "stable" state). + // From then on, the preview headers are not required anymore to activate the additional + // feature on GitHub.com's API. However, this API header might still be needed for users + // to run a GitHub Enterprise Server on-premise. + // It's not uncommon for GitHub Enterprise Server customers to run older versions which + // would probably rely on the preview headers for some time. + // While the header promotion is going out for GitHub.com, it may be some time before it + // even arrives in GitHub Enterprise Server. + // We keep those preview headers around to avoid breaking older GitHub Enterprise Server + // versions. Additionally, non-functional (preview) headers don't create any side effects + // on GitHub Cloud version. + // + // See https://github.com/google/go-github/pull/2125 for full context. + + // https://developer.github.com/changes/2014-12-09-new-attributes-for-stars-api/ + mediaTypeStarringPreview = "application/vnd.github.v3.star+json" + + // https://help.github.com/enterprise/2.4/admin/guides/migrations/exporting-the-gitproxy.zycloud.tk-organization-s-repositories/ + mediaTypeMigrationsPreview = "application/vnd.github.wyandotte-preview+json" + + // https://developer.github.com/changes/2016-04-06-deployment-and-deployment-status-enhancements/ + mediaTypeDeploymentStatusPreview = "application/vnd.github.ant-man-preview+json" + + // https://developer.github.com/changes/2018-10-16-deployments-environments-states-and-auto-inactive-updates/ + mediaTypeExpandDeploymentStatusPreview = "application/vnd.github.flash-preview+json" + + // https://developer.github.com/changes/2016-05-12-reactions-api-preview/ + mediaTypeReactionsPreview = "application/vnd.github.squirrel-girl-preview" + + // https://developer.github.com/changes/2016-05-23-timeline-preview-api/ + mediaTypeTimelinePreview = "application/vnd.github.mockingbird-preview+json" + + // https://developer.github.com/changes/2016-09-14-projects-api/ + mediaTypeProjectsPreview = "application/vnd.github.inertia-preview+json" + + // https://developer.github.com/changes/2017-01-05-commit-search-api/ + mediaTypeCommitSearchPreview = "application/vnd.github.cloak-preview+json" + + // https://developer.github.com/changes/2017-02-28-user-blocking-apis-and-webhook/ + mediaTypeBlockUsersPreview = "application/vnd.github.giant-sentry-fist-preview+json" + + // https://developer.github.com/changes/2017-05-23-coc-api/ + mediaTypeCodesOfConductPreview = "application/vnd.github.scarlet-witch-preview+json" + + // https://developer.github.com/changes/2017-07-17-update-topics-on-repositories/ + mediaTypeTopicsPreview = "application/vnd.github.mercy-preview+json" + + // https://developer.github.com/changes/2018-03-16-protected-branches-required-approving-reviews/ + mediaTypeRequiredApprovingReviewsPreview = "application/vnd.github.luke-cage-preview+json" + + // https://developer.github.com/changes/2018-05-07-new-checks-api-public-beta/ + mediaTypeCheckRunsPreview = "application/vnd.github.antiope-preview+json" + + // https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/ + mediaTypePreReceiveHooksPreview = "application/vnd.github.eye-scream-preview" + + // https://developer.github.com/changes/2018-02-22-protected-branches-required-signatures/ + mediaTypeSignaturePreview = "application/vnd.github.zzzax-preview+json" + + // https://developer.github.com/changes/2018-09-05-project-card-events/ + mediaTypeProjectCardDetailsPreview = "application/vnd.github.starfox-preview+json" + + // https://developer.github.com/changes/2018-12-18-interactions-preview/ + mediaTypeInteractionRestrictionsPreview = "application/vnd.github.sombra-preview+json" + + // https://developer.github.com/changes/2019-03-14-enabling-disabling-pages/ + mediaTypeEnablePagesAPIPreview = "application/vnd.github.switcheroo-preview+json" + + // https://developer.github.com/changes/2019-04-24-vulnerability-alerts/ + mediaTypeRequiredVulnerabilityAlertsPreview = "application/vnd.github.dorian-preview+json" + + // https://developer.github.com/changes/2019-06-04-automated-security-fixes/ + mediaTypeRequiredAutomatedSecurityFixesPreview = "application/vnd.github.london-preview+json" + + // https://developer.github.com/changes/2019-05-29-update-branch-api/ + mediaTypeUpdatePullRequestBranchPreview = "application/vnd.github.lydian-preview+json" + + // https://developer.github.com/changes/2019-04-11-pulls-branches-for-commit/ + mediaTypeListPullsOrBranchesForCommitPreview = "application/vnd.github.groot-preview+json" + + // https://docs.github.com/en/rest/previews/#repository-creation-permissions + mediaTypeMemberAllowedRepoCreationTypePreview = "application/vnd.github.surtur-preview+json" + + // https://docs.github.com/en/rest/previews/#create-and-use-repository-templates + mediaTypeRepositoryTemplatePreview = "application/vnd.github.baptiste-preview+json" + + // https://developer.github.com/changes/2019-10-03-multi-line-comments/ + mediaTypeMultiLineCommentsPreview = "application/vnd.github.comfort-fade-preview+json" + + // https://developer.github.com/changes/2019-11-05-deprecated-passwords-and-authorizations-api/ + mediaTypeOAuthAppPreview = "application/vnd.github.doctor-strange-preview+json" + + // https://developer.github.com/changes/2019-12-03-internal-visibility-changes/ + mediaTypeRepositoryVisibilityPreview = "application/vnd.github.nebula-preview+json" + + // https://developer.github.com/changes/2018-12-10-content-attachments-api/ + mediaTypeContentAttachmentsPreview = "application/vnd.github.corsair-preview+json" +) + +var errNonNilContext = errors.New("context must be non-nil") + +// A Client manages communication with the GitHub API. +type Client struct { + clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func. + client *http.Client // HTTP client used to communicate with the API. + + // Base URL for API requests. Defaults to the public GitHub API, but can be + // set to a domain endpoint to use with GitHub Enterprise. BaseURL should + // always be specified with a trailing slash. + BaseURL *url.URL + + // Base URL for uploading files. + UploadURL *url.URL + + // User agent used when communicating with the GitHub API. + UserAgent string + + rateMu sync.Mutex + rateLimits [categories]Rate // Rate limits for the client as determined by the most recent API calls. + + common service // Reuse a single struct instead of allocating one for each service on the heap. + + // Services used for talking to different parts of the GitHub API. + Actions *ActionsService + Activity *ActivityService + Admin *AdminService + Apps *AppsService + Authorizations *AuthorizationsService + Billing *BillingService + Checks *ChecksService + CodeScanning *CodeScanningService + Dependabot *DependabotService + Enterprise *EnterpriseService + Gists *GistsService + Git *GitService + Gitignores *GitignoresService + Interactions *InteractionsService + IssueImport *IssueImportService + Issues *IssuesService + Licenses *LicensesService + Marketplace *MarketplaceService + Migrations *MigrationService + Organizations *OrganizationsService + Projects *ProjectsService + PullRequests *PullRequestsService + Reactions *ReactionsService + Repositories *RepositoriesService + SCIM *SCIMService + Search *SearchService + SecretScanning *SecretScanningService + Teams *TeamsService + Users *UsersService +} + +type service struct { + client *Client +} + +// Client returns the http.Client used by this GitHub client. +func (c *Client) Client() *http.Client { + c.clientMu.Lock() + defer c.clientMu.Unlock() + clientCopy := *c.client + return &clientCopy +} + +// ListOptions specifies the optional parameters to various List methods that +// support offset pagination. +type ListOptions struct { + // For paginated result sets, page of results to retrieve. + Page int `url:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty"` +} + +// ListCursorOptions specifies the optional parameters to various List methods that +// support cursor pagination. +type ListCursorOptions struct { + // For paginated result sets, page of results to retrieve. + Page string `url:"page,omitempty"` + + // For paginated result sets, the number of results to include per page. + PerPage int `url:"per_page,omitempty"` + + // A cursor, as given in the Link header. If specified, the query only searches for events after this cursor. + After string `url:"after,omitempty"` + + // A cursor, as given in the Link header. If specified, the query only searches for events before this cursor. + Before string `url:"before,omitempty"` + + // A cursor, as given in the Link header. If specified, the query continues the search using this cursor. + Cursor string `url:"cursor,omitempty"` +} + +// UploadOptions specifies the parameters to methods that support uploads. +type UploadOptions struct { + Name string `url:"name,omitempty"` + Label string `url:"label,omitempty"` + MediaType string `url:"-"` +} + +// RawType represents type of raw format of a request instead of JSON. +type RawType uint8 + +const ( + // Diff format. + Diff RawType = 1 + iota + // Patch format. + Patch +) + +// RawOptions specifies parameters when user wants to get raw format of +// a response instead of JSON. +type RawOptions struct { + Type RawType +} + +// addOptions adds the parameters in opts as URL query parameters to s. opts +// must be a struct whose fields may contain "url" tags. +func addOptions(s string, opts interface{}) (string, error) { + v := reflect.ValueOf(opts) + if v.Kind() == reflect.Ptr && v.IsNil() { + return s, nil + } + + u, err := url.Parse(s) + if err != nil { + return s, err + } + + qs, err := query.Values(opts) + if err != nil { + return s, err + } + + u.RawQuery = qs.Encode() + return u.String(), nil +} + +// NewClient returns a new GitHub API client. If a nil httpClient is +// provided, a new http.Client will be used. To use API methods which require +// authentication, provide an http.Client that will perform the authentication +// for you (such as that provided by the golang.org/x/oauth2 library). +func NewClient(httpClient *http.Client) *Client { + if httpClient == nil { + httpClient = &http.Client{} + } + baseURL, _ := url.Parse(defaultBaseURL) + uploadURL, _ := url.Parse(uploadBaseURL) + + c := &Client{client: httpClient, BaseURL: baseURL, UserAgent: userAgent, UploadURL: uploadURL} + c.common.client = c + c.Actions = (*ActionsService)(&c.common) + c.Activity = (*ActivityService)(&c.common) + c.Admin = (*AdminService)(&c.common) + c.Apps = (*AppsService)(&c.common) + c.Authorizations = (*AuthorizationsService)(&c.common) + c.Billing = (*BillingService)(&c.common) + c.Checks = (*ChecksService)(&c.common) + c.CodeScanning = (*CodeScanningService)(&c.common) + c.Dependabot = (*DependabotService)(&c.common) + c.Enterprise = (*EnterpriseService)(&c.common) + c.Gists = (*GistsService)(&c.common) + c.Git = (*GitService)(&c.common) + c.Gitignores = (*GitignoresService)(&c.common) + c.Interactions = (*InteractionsService)(&c.common) + c.IssueImport = (*IssueImportService)(&c.common) + c.Issues = (*IssuesService)(&c.common) + c.Licenses = (*LicensesService)(&c.common) + c.Marketplace = &MarketplaceService{client: c} + c.Migrations = (*MigrationService)(&c.common) + c.Organizations = (*OrganizationsService)(&c.common) + c.Projects = (*ProjectsService)(&c.common) + c.PullRequests = (*PullRequestsService)(&c.common) + c.Reactions = (*ReactionsService)(&c.common) + c.Repositories = (*RepositoriesService)(&c.common) + c.SCIM = (*SCIMService)(&c.common) + c.Search = (*SearchService)(&c.common) + c.SecretScanning = (*SecretScanningService)(&c.common) + c.Teams = (*TeamsService)(&c.common) + c.Users = (*UsersService)(&c.common) + return c +} + +// NewEnterpriseClient returns a new GitHub API client with provided +// base URL and upload URL (often is your GitHub Enterprise hostname). +// If the base URL does not have the suffix "/api/v3/", it will be added automatically. +// If the upload URL does not have the suffix "/api/uploads", it will be added automatically. +// If a nil httpClient is provided, a new http.Client will be used. +// +// Note that NewEnterpriseClient is a convenience helper only; +// its behavior is equivalent to using NewClient, followed by setting +// the BaseURL and UploadURL fields. +// +// Another important thing is that by default, the GitHub Enterprise URL format +// should be http(s)://[hostname]/api/v3/ or you will always receive the 406 status code. +// The upload URL format should be http(s)://[hostname]/api/uploads/. +func NewEnterpriseClient(baseURL, uploadURL string, httpClient *http.Client) (*Client, error) { + baseEndpoint, err := url.Parse(baseURL) + if err != nil { + return nil, err + } + + if !strings.HasSuffix(baseEndpoint.Path, "/") { + baseEndpoint.Path += "/" + } + if !strings.HasSuffix(baseEndpoint.Path, "/api/v3/") && + !strings.HasPrefix(baseEndpoint.Host, "api.") && + !strings.Contains(baseEndpoint.Host, ".api.") { + baseEndpoint.Path += "api/v3/" + } + + uploadEndpoint, err := url.Parse(uploadURL) + if err != nil { + return nil, err + } + + if !strings.HasSuffix(uploadEndpoint.Path, "/") { + uploadEndpoint.Path += "/" + } + if !strings.HasSuffix(uploadEndpoint.Path, "/api/uploads/") && + !strings.HasPrefix(uploadEndpoint.Host, "api.") && + !strings.Contains(uploadEndpoint.Host, ".api.") { + uploadEndpoint.Path += "api/uploads/" + } + + c := NewClient(httpClient) + c.BaseURL = baseEndpoint + c.UploadURL = uploadEndpoint + return c, nil +} + +// NewRequest creates an API request. A relative URL can be provided in urlStr, +// in which case it is resolved relative to the BaseURL of the Client. +// Relative URLs should always be specified without a preceding slash. If +// specified, the value pointed to by body is JSON encoded and included as the +// request body. +func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error) { + if !strings.HasSuffix(c.BaseURL.Path, "/") { + return nil, fmt.Errorf("BaseURL must have a trailing slash, but %q does not", c.BaseURL) + } + + u, err := c.BaseURL.Parse(urlStr) + if err != nil { + return nil, err + } + + var buf io.ReadWriter + if body != nil { + buf = &bytes.Buffer{} + enc := json.NewEncoder(buf) + enc.SetEscapeHTML(false) + err := enc.Encode(body) + if err != nil { + return nil, err + } + } + + req, err := http.NewRequest(method, u.String(), buf) + if err != nil { + return nil, err + } + + if body != nil { + req.Header.Set("Content-Type", "application/json") + } + req.Header.Set("Accept", mediaTypeV3) + if c.UserAgent != "" { + req.Header.Set("User-Agent", c.UserAgent) + } + return req, nil +} + +// NewUploadRequest creates an upload request. A relative URL can be provided in +// urlStr, in which case it is resolved relative to the UploadURL of the Client. +// Relative URLs should always be specified without a preceding slash. +func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string) (*http.Request, error) { + if !strings.HasSuffix(c.UploadURL.Path, "/") { + return nil, fmt.Errorf("UploadURL must have a trailing slash, but %q does not", c.UploadURL) + } + u, err := c.UploadURL.Parse(urlStr) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", u.String(), reader) + if err != nil { + return nil, err + } + + req.ContentLength = size + + if mediaType == "" { + mediaType = defaultMediaType + } + req.Header.Set("Content-Type", mediaType) + req.Header.Set("Accept", mediaTypeV3) + req.Header.Set("User-Agent", c.UserAgent) + return req, nil +} + +// Response is a GitHub API response. This wraps the standard http.Response +// returned from GitHub and provides convenient access to things like +// pagination links. +type Response struct { + *http.Response + + // These fields provide the page values for paginating through a set of + // results. Any or all of these may be set to the zero value for + // responses that are not part of a paginated set, or for which there + // are no additional pages. + // + // These fields support what is called "offset pagination" and should + // be used with the ListOptions struct. + NextPage int + PrevPage int + FirstPage int + LastPage int + + // Additionally, some APIs support "cursor pagination" instead of offset. + // This means that a token points directly to the next record which + // can lead to O(1) performance compared to O(n) performance provided + // by offset pagination. + // + // For APIs that support cursor pagination (such as + // TeamsService.ListIDPGroupsInOrganization), the following field + // will be populated to point to the next page. + // + // To use this token, set ListCursorOptions.Page to this value before + // calling the endpoint again. + NextPageToken string + + // For APIs that support cursor pagination, such as RepositoriesService.ListHookDeliveries, + // the following field will be populated to point to the next page. + // Set ListCursorOptions.Cursor to this value when calling the endpoint again. + Cursor string + + // For APIs that support before/after pagination, such as OrganizationsService.AuditLog. + Before string + After string + + // Explicitly specify the Rate type so Rate's String() receiver doesn't + // propagate to Response. + Rate Rate + + // token's expiration date + TokenExpiration Timestamp +} + +// newResponse creates a new Response for the provided http.Response. +// r must not be nil. +func newResponse(r *http.Response) *Response { + response := &Response{Response: r} + response.populatePageValues() + response.Rate = parseRate(r) + response.TokenExpiration = parseTokenExpiration(r) + return response +} + +// populatePageValues parses the HTTP Link response headers and populates the +// various pagination link values in the Response. +func (r *Response) populatePageValues() { + if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 { + for _, link := range strings.Split(links[0], ",") { + segments := strings.Split(strings.TrimSpace(link), ";") + + // link must at least have href and rel + if len(segments) < 2 { + continue + } + + // ensure href is properly formatted + if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") { + continue + } + + // try to pull out page parameter + url, err := url.Parse(segments[0][1 : len(segments[0])-1]) + if err != nil { + continue + } + + q := url.Query() + + if cursor := q.Get("cursor"); cursor != "" { + for _, segment := range segments[1:] { + switch strings.TrimSpace(segment) { + case `rel="next"`: + r.Cursor = cursor + } + } + + continue + } + + page := q.Get("page") + since := q.Get("since") + before := q.Get("before") + after := q.Get("after") + + if page == "" && before == "" && after == "" && since == "" { + continue + } + + if since != "" && page == "" { + page = since + } + + for _, segment := range segments[1:] { + switch strings.TrimSpace(segment) { + case `rel="next"`: + if r.NextPage, err = strconv.Atoi(page); err != nil { + r.NextPageToken = page + } + r.After = after + case `rel="prev"`: + r.PrevPage, _ = strconv.Atoi(page) + r.Before = before + case `rel="first"`: + r.FirstPage, _ = strconv.Atoi(page) + case `rel="last"`: + r.LastPage, _ = strconv.Atoi(page) + } + } + } + } +} + +// parseRate parses the rate related headers. +func parseRate(r *http.Response) Rate { + var rate Rate + if limit := r.Header.Get(headerRateLimit); limit != "" { + rate.Limit, _ = strconv.Atoi(limit) + } + if remaining := r.Header.Get(headerRateRemaining); remaining != "" { + rate.Remaining, _ = strconv.Atoi(remaining) + } + if reset := r.Header.Get(headerRateReset); reset != "" { + if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { + rate.Reset = Timestamp{time.Unix(v, 0)} + } + } + return rate +} + +// parseTokenExpiration parses the TokenExpiration related headers. +func parseTokenExpiration(r *http.Response) Timestamp { + var exp Timestamp + if v := r.Header.Get(headerTokenExpiration); v != "" { + if t, err := time.Parse("2006-01-02 03:04:05 MST", v); err == nil { + exp = Timestamp{t.Local()} + } + } + return exp +} + +type requestContext uint8 + +const ( + bypassRateLimitCheck requestContext = iota +) + +// BareDo sends an API request and lets you handle the api response. If an error +// or API Error occurs, the error will contain more information. Otherwise you +// are supposed to read and close the response's Body. If rate limit is exceeded +// and reset time is in the future, BareDo returns *RateLimitError immediately +// without making a network API call. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it is +// canceled or times out, ctx.Err() will be returned. +func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, error) { + if ctx == nil { + return nil, errNonNilContext + } + + req = withContext(ctx, req) + + rateLimitCategory := category(req.URL.Path) + + if bypass := ctx.Value(bypassRateLimitCheck); bypass == nil { + // If we've hit rate limit, don't make further requests before Reset time. + if err := c.checkRateLimitBeforeDo(req, rateLimitCategory); err != nil { + return &Response{ + Response: err.Response, + Rate: err.Rate, + }, err + } + } + + resp, err := c.client.Do(req) + if err != nil { + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + select { + case <-ctx.Done(): + return nil, ctx.Err() + default: + } + + // If the error type is *url.Error, sanitize its URL before returning. + if e, ok := err.(*url.Error); ok { + if url, err := url.Parse(e.URL); err == nil { + e.URL = sanitizeURL(url).String() + return nil, e + } + } + + return nil, err + } + + response := newResponse(resp) + + // Don't update the rate limits if this was a cached response. + // X-From-Cache is set by https://github.com/gregjones/httpcache + if response.Header.Get("X-From-Cache") == "" { + c.rateMu.Lock() + c.rateLimits[rateLimitCategory] = response.Rate + c.rateMu.Unlock() + } + + err = CheckResponse(resp) + if err != nil { + defer resp.Body.Close() + // Special case for AcceptedErrors. If an AcceptedError + // has been encountered, the response's payload will be + // added to the AcceptedError and returned. + // + // Issue #1022 + aerr, ok := err.(*AcceptedError) + if ok { + b, readErr := ioutil.ReadAll(resp.Body) + if readErr != nil { + return response, readErr + } + + aerr.Raw = b + err = aerr + } + } + return response, err +} + +// Do sends an API request and returns the API response. The API response is +// JSON decoded and stored in the value pointed to by v, or returned as an +// error if an API error has occurred. If v implements the io.Writer interface, +// the raw response body will be written to v, without attempting to first +// decode it. If v is nil, and no error hapens, the response is returned as is. +// If rate limit is exceeded and reset time is in the future, Do returns +// *RateLimitError immediately without making a network API call. +// +// The provided ctx must be non-nil, if it is nil an error is returned. If it +// is canceled or times out, ctx.Err() will be returned. +func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error) { + resp, err := c.BareDo(ctx, req) + if err != nil { + return resp, err + } + defer resp.Body.Close() + + switch v := v.(type) { + case nil: + case io.Writer: + _, err = io.Copy(v, resp.Body) + default: + decErr := json.NewDecoder(resp.Body).Decode(v) + if decErr == io.EOF { + decErr = nil // ignore EOF errors caused by empty response body + } + if decErr != nil { + err = decErr + } + } + return resp, err +} + +// checkRateLimitBeforeDo does not make any network calls, but uses existing knowledge from +// current client state in order to quickly check if *RateLimitError can be immediately returned +// from Client.Do, and if so, returns it so that Client.Do can skip making a network API call unnecessarily. +// Otherwise it returns nil, and Client.Do should proceed normally. +func (c *Client) checkRateLimitBeforeDo(req *http.Request, rateLimitCategory rateLimitCategory) *RateLimitError { + c.rateMu.Lock() + rate := c.rateLimits[rateLimitCategory] + c.rateMu.Unlock() + if !rate.Reset.Time.IsZero() && rate.Remaining == 0 && time.Now().Before(rate.Reset.Time) { + // Create a fake response. + resp := &http.Response{ + Status: http.StatusText(http.StatusForbidden), + StatusCode: http.StatusForbidden, + Request: req, + Header: make(http.Header), + Body: ioutil.NopCloser(strings.NewReader("")), + } + return &RateLimitError{ + Rate: rate, + Response: resp, + Message: fmt.Sprintf("API rate limit of %v still exceeded until %v, not making remote request.", rate.Limit, rate.Reset.Time), + } + } + + return nil +} + +// compareHTTPResponse returns whether two http.Response objects are equal or not. +// Currently, only StatusCode is checked. This function is used when implementing the +// Is(error) bool interface for the custom error types in this package. +func compareHTTPResponse(r1, r2 *http.Response) bool { + if r1 == nil && r2 == nil { + return true + } + + if r1 != nil && r2 != nil { + return r1.StatusCode == r2.StatusCode + } + return false +} + +/* +An ErrorResponse reports one or more errors caused by an API request. + +GitHub API docs: https://docs.github.com/en/rest/#client-errors +*/ +type ErrorResponse struct { + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message + Errors []Error `json:"errors"` // more detail on individual errors + // Block is only populated on certain types of errors such as code 451. + Block *ErrorBlock `json:"block,omitempty"` + // Most errors will also include a documentation_url field pointing + // to some content that might help you resolve the error, see + // https://docs.github.com/en/rest/#client-errors + DocumentationURL string `json:"documentation_url,omitempty"` +} + +// ErrorBlock contains a further explanation for the reason of an error. +// See https://developer.github.com/changes/2016-03-17-the-451-status-code-is-now-supported/ +// for more information. +type ErrorBlock struct { + Reason string `json:"reason,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +func (r *ErrorResponse) Error() string { + return fmt.Sprintf("%v %v: %d %v %+v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message, r.Errors) +} + +// Is returns whether the provided error equals this error. +func (r *ErrorResponse) Is(target error) bool { + v, ok := target.(*ErrorResponse) + if !ok { + return false + } + + if r.Message != v.Message || (r.DocumentationURL != v.DocumentationURL) || + !compareHTTPResponse(r.Response, v.Response) { + return false + } + + // Compare Errors. + if len(r.Errors) != len(v.Errors) { + return false + } + for idx := range r.Errors { + if r.Errors[idx] != v.Errors[idx] { + return false + } + } + + // Compare Block. + if (r.Block != nil && v.Block == nil) || (r.Block == nil && v.Block != nil) { + return false + } + if r.Block != nil && v.Block != nil { + if r.Block.Reason != v.Block.Reason { + return false + } + if (r.Block.CreatedAt != nil && v.Block.CreatedAt == nil) || (r.Block.CreatedAt == + nil && v.Block.CreatedAt != nil) { + return false + } + if r.Block.CreatedAt != nil && v.Block.CreatedAt != nil { + if *(r.Block.CreatedAt) != *(v.Block.CreatedAt) { + return false + } + } + } + + return true +} + +// TwoFactorAuthError occurs when using HTTP Basic Authentication for a user +// that has two-factor authentication enabled. The request can be reattempted +// by providing a one-time password in the request. +type TwoFactorAuthError ErrorResponse + +func (r *TwoFactorAuthError) Error() string { return (*ErrorResponse)(r).Error() } + +// RateLimitError occurs when GitHub returns 403 Forbidden response with a rate limit +// remaining value of 0. +type RateLimitError struct { + Rate Rate // Rate specifies last known rate limit for the client + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message +} + +func (r *RateLimitError) Error() string { + return fmt.Sprintf("%v %v: %d %v %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message, formatRateReset(time.Until(r.Rate.Reset.Time))) +} + +// Is returns whether the provided error equals this error. +func (r *RateLimitError) Is(target error) bool { + v, ok := target.(*RateLimitError) + if !ok { + return false + } + + return r.Rate == v.Rate && + r.Message == v.Message && + compareHTTPResponse(r.Response, v.Response) +} + +// AcceptedError occurs when GitHub returns 202 Accepted response with an +// empty body, which means a job was scheduled on the GitHub side to process +// the information needed and cache it. +// Technically, 202 Accepted is not a real error, it's just used to +// indicate that results are not ready yet, but should be available soon. +// The request can be repeated after some time. +type AcceptedError struct { + // Raw contains the response body. + Raw []byte +} + +func (*AcceptedError) Error() string { + return "job scheduled on GitHub side; try again later" +} + +// Is returns whether the provided error equals this error. +func (ae *AcceptedError) Is(target error) bool { + v, ok := target.(*AcceptedError) + if !ok { + return false + } + return bytes.Compare(ae.Raw, v.Raw) == 0 +} + +// AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the +// "documentation_url" field value equal to "https://docs.github.com/en/rest/overview/resources-in-the-rest-api#secondary-rate-limits". +type AbuseRateLimitError struct { + Response *http.Response // HTTP response that caused this error + Message string `json:"message"` // error message + + // RetryAfter is provided with some abuse rate limit errors. If present, + // it is the amount of time that the client should wait before retrying. + // Otherwise, the client should try again later (after an unspecified amount of time). + RetryAfter *time.Duration +} + +func (r *AbuseRateLimitError) Error() string { + return fmt.Sprintf("%v %v: %d %v", + r.Response.Request.Method, sanitizeURL(r.Response.Request.URL), + r.Response.StatusCode, r.Message) +} + +// Is returns whether the provided error equals this error. +func (r *AbuseRateLimitError) Is(target error) bool { + v, ok := target.(*AbuseRateLimitError) + if !ok { + return false + } + + return r.Message == v.Message && + r.RetryAfter == v.RetryAfter && + compareHTTPResponse(r.Response, v.Response) +} + +// sanitizeURL redacts the client_secret parameter from the URL which may be +// exposed to the user. +func sanitizeURL(uri *url.URL) *url.URL { + if uri == nil { + return nil + } + params := uri.Query() + if len(params.Get("client_secret")) > 0 { + params.Set("client_secret", "REDACTED") + uri.RawQuery = params.Encode() + } + return uri +} + +/* +An Error reports more details on an individual error in an ErrorResponse. +These are the possible validation error codes: + + missing: + resource does not exist + missing_field: + a required field on a resource has not been set + invalid: + the formatting of a field is invalid + already_exists: + another resource has the same valid as this field + custom: + some resources return this (e.g. github.User.CreateKey()), additional + information is set in the Message field of the Error + +GitHub error responses structure are often undocumented and inconsistent. +Sometimes error is just a simple string (Issue #540). +In such cases, Message represents an error message as a workaround. + +GitHub API docs: https://docs.github.com/en/rest/#client-errors +*/ +type Error struct { + Resource string `json:"resource"` // resource on which the error occurred + Field string `json:"field"` // field on which the error occurred + Code string `json:"code"` // validation error code + Message string `json:"message"` // Message describing the error. Errors with Code == "custom" will always have this set. +} + +func (e *Error) Error() string { + return fmt.Sprintf("%v error caused by %v field on %v resource", + e.Code, e.Field, e.Resource) +} + +func (e *Error) UnmarshalJSON(data []byte) error { + type aliasError Error // avoid infinite recursion by using type alias. + if err := json.Unmarshal(data, (*aliasError)(e)); err != nil { + return json.Unmarshal(data, &e.Message) // data can be json string. + } + return nil +} + +// CheckResponse checks the API response for errors, and returns them if +// present. A response is considered an error if it has a status code outside +// the 200 range or equal to 202 Accepted. +// API error responses are expected to have response +// body, and a JSON response body that maps to ErrorResponse. +// +// The error type will be *RateLimitError for rate limit exceeded errors, +// *AcceptedError for 202 Accepted status codes, +// and *TwoFactorAuthError for two-factor authentication errors. +func CheckResponse(r *http.Response) error { + if r.StatusCode == http.StatusAccepted { + return &AcceptedError{} + } + if c := r.StatusCode; 200 <= c && c <= 299 { + return nil + } + + errorResponse := &ErrorResponse{Response: r} + data, err := ioutil.ReadAll(r.Body) + if err == nil && data != nil { + json.Unmarshal(data, errorResponse) + } + // Re-populate error response body because GitHub error responses are often + // undocumented and inconsistent. + // Issue #1136, #540. + r.Body = ioutil.NopCloser(bytes.NewBuffer(data)) + switch { + case r.StatusCode == http.StatusUnauthorized && strings.HasPrefix(r.Header.Get(headerOTP), "required"): + return (*TwoFactorAuthError)(errorResponse) + case r.StatusCode == http.StatusForbidden && r.Header.Get(headerRateRemaining) == "0": + return &RateLimitError{ + Rate: parseRate(r), + Response: errorResponse.Response, + Message: errorResponse.Message, + } + case r.StatusCode == http.StatusForbidden && + (strings.HasSuffix(errorResponse.DocumentationURL, "#abuse-rate-limits") || + strings.HasSuffix(errorResponse.DocumentationURL, "#secondary-rate-limits")): + abuseRateLimitError := &AbuseRateLimitError{ + Response: errorResponse.Response, + Message: errorResponse.Message, + } + if v := r.Header["Retry-After"]; len(v) > 0 { + // According to GitHub support, the "Retry-After" header value will be + // an integer which represents the number of seconds that one should + // wait before resuming making requests. + retryAfterSeconds, _ := strconv.ParseInt(v[0], 10, 64) // Error handling is noop. + retryAfter := time.Duration(retryAfterSeconds) * time.Second + abuseRateLimitError.RetryAfter = &retryAfter + } + return abuseRateLimitError + default: + return errorResponse + } +} + +// parseBoolResponse determines the boolean result from a GitHub API response. +// Several GitHub API methods return boolean responses indicated by the HTTP +// status code in the response (true indicated by a 204, false indicated by a +// 404). This helper function will determine that result and hide the 404 +// error if present. Any other error will be returned through as-is. +func parseBoolResponse(err error) (bool, error) { + if err == nil { + return true, nil + } + + if err, ok := err.(*ErrorResponse); ok && err.Response.StatusCode == http.StatusNotFound { + // Simply false. In this one case, we do not pass the error through. + return false, nil + } + + // some other real error occurred + return false, err +} + +// Rate represents the rate limit for the current client. +type Rate struct { + // The number of requests per hour the client is currently limited to. + Limit int `json:"limit"` + + // The number of remaining requests the client can make this hour. + Remaining int `json:"remaining"` + + // The time at which the current rate limit will reset. + Reset Timestamp `json:"reset"` +} + +func (r Rate) String() string { + return Stringify(r) +} + +// RateLimits represents the rate limits for the current client. +type RateLimits struct { + // The rate limit for non-search API requests. Unauthenticated + // requests are limited to 60 per hour. Authenticated requests are + // limited to 5,000 per hour. + // + // GitHub API docs: https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting + Core *Rate `json:"core"` + + // The rate limit for search API requests. Unauthenticated requests + // are limited to 10 requests per minutes. Authenticated requests are + // limited to 30 per minute. + // + // GitHub API docs: https://docs.github.com/en/rest/search#rate-limit + Search *Rate `json:"search"` + + // GitHub API docs: https://docs.github.com/en/graphql/overview/resource-limitations#rate-limit + GraphQL *Rate `json:"graphql"` + + // GitHub API dos: https://docs.github.com/en/rest/rate-limit + IntegrationManifest *Rate `json:"integration_manifest"` + + SourceImport *Rate `json:"source_import"` + CodeScanningUpload *Rate `json:"code_scanning_upload"` + ActionsRunnerRegistration *Rate `json:"actions_runner_registration"` + SCIM *Rate `json:"scim"` +} + +func (r RateLimits) String() string { + return Stringify(r) +} + +type rateLimitCategory uint8 + +const ( + coreCategory rateLimitCategory = iota + searchCategory + graphqlCategory + integrationManifestCategory + sourceImportCategory + codeScanningUploadCategory + actionsRunnerRegistrationCategory + scimCategory + + categories // An array of this length will be able to contain all rate limit categories. +) + +// category returns the rate limit category of the endpoint, determined by Request.URL.Path. +func category(path string) rateLimitCategory { + switch { + default: + return coreCategory + case strings.HasPrefix(path, "/search/"): + return searchCategory + } +} + +// RateLimits returns the rate limits for the current client. +func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error) { + req, err := c.NewRequest("GET", "rate_limit", nil) + if err != nil { + return nil, nil, err + } + + response := new(struct { + Resources *RateLimits `json:"resources"` + }) + + // This resource is not subject to rate limits. + ctx = context.WithValue(ctx, bypassRateLimitCheck, true) + resp, err := c.Do(ctx, req, response) + if err != nil { + return nil, resp, err + } + + if response.Resources != nil { + c.rateMu.Lock() + if response.Resources.Core != nil { + c.rateLimits[coreCategory] = *response.Resources.Core + } + if response.Resources.Search != nil { + c.rateLimits[searchCategory] = *response.Resources.Search + } + if response.Resources.GraphQL != nil { + c.rateLimits[graphqlCategory] = *response.Resources.GraphQL + } + if response.Resources.IntegrationManifest != nil { + c.rateLimits[integrationManifestCategory] = *response.Resources.IntegrationManifest + } + if response.Resources.SourceImport != nil { + c.rateLimits[sourceImportCategory] = *response.Resources.SourceImport + } + if response.Resources.CodeScanningUpload != nil { + c.rateLimits[codeScanningUploadCategory] = *response.Resources.CodeScanningUpload + } + if response.Resources.ActionsRunnerRegistration != nil { + c.rateLimits[actionsRunnerRegistrationCategory] = *response.Resources.ActionsRunnerRegistration + } + if response.Resources.SCIM != nil { + c.rateLimits[scimCategory] = *response.Resources.SCIM + } + c.rateMu.Unlock() + } + + return response.Resources, resp, nil +} + +func setCredentialsAsHeaders(req *http.Request, id, secret string) *http.Request { + // To set extra headers, we must make a copy of the Request so + // that we don't modify the Request we were given. This is required by the + // specification of http.RoundTripper. + // + // Since we are going to modify only req.Header here, we only need a deep copy + // of req.Header. + convertedRequest := new(http.Request) + *convertedRequest = *req + convertedRequest.Header = make(http.Header, len(req.Header)) + + for k, s := range req.Header { + convertedRequest.Header[k] = append([]string(nil), s...) + } + convertedRequest.SetBasicAuth(id, secret) + return convertedRequest +} + +/* +UnauthenticatedRateLimitedTransport allows you to make unauthenticated calls +that need to use a higher rate limit associated with your OAuth application. + + t := &github.UnauthenticatedRateLimitedTransport{ + ClientID: "your app's client ID", + ClientSecret: "your app's client secret", + } + client := github.NewClient(t.Client()) + +This will add the client id and secret as a base64-encoded string in the format +ClientID:ClientSecret and apply it as an "Authorization": "Basic" header. + +See https://docs.github.com/en/rest/#unauthenticated-rate-limited-requests for +more information. +*/ +type UnauthenticatedRateLimitedTransport struct { + // ClientID is the GitHub OAuth client ID of the current application, which + // can be found by selecting its entry in the list at + // https://github.com/settings/applications. + ClientID string + + // ClientSecret is the GitHub OAuth client secret of the current + // application. + ClientSecret string + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (t *UnauthenticatedRateLimitedTransport) RoundTrip(req *http.Request) (*http.Response, error) { + if t.ClientID == "" { + return nil, errors.New("t.ClientID is empty") + } + if t.ClientSecret == "" { + return nil, errors.New("t.ClientSecret is empty") + } + + req2 := setCredentialsAsHeaders(req, t.ClientID, t.ClientSecret) + // Make the HTTP request. + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests which are subject to the +// rate limit of your OAuth application. +func (t *UnauthenticatedRateLimitedTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *UnauthenticatedRateLimitedTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// BasicAuthTransport is an http.RoundTripper that authenticates all requests +// using HTTP Basic Authentication with the provided username and password. It +// additionally supports users who have two-factor authentication enabled on +// their GitHub account. +type BasicAuthTransport struct { + Username string // GitHub username + Password string // GitHub password + OTP string // one-time password for users with two-factor auth enabled + + // Transport is the underlying HTTP transport to use when making requests. + // It will default to http.DefaultTransport if nil. + Transport http.RoundTripper +} + +// RoundTrip implements the RoundTripper interface. +func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) { + req2 := setCredentialsAsHeaders(req, t.Username, t.Password) + if t.OTP != "" { + req2.Header.Set(headerOTP, t.OTP) + } + return t.transport().RoundTrip(req2) +} + +// Client returns an *http.Client that makes requests that are authenticated +// using HTTP Basic Authentication. +func (t *BasicAuthTransport) Client() *http.Client { + return &http.Client{Transport: t} +} + +func (t *BasicAuthTransport) transport() http.RoundTripper { + if t.Transport != nil { + return t.Transport + } + return http.DefaultTransport +} + +// formatRateReset formats d to look like "[rate reset in 2s]" or +// "[rate reset in 87m02s]" for the positive durations. And like "[rate limit was reset 87m02s ago]" +// for the negative cases. +func formatRateReset(d time.Duration) string { + isNegative := d < 0 + if isNegative { + d *= -1 + } + secondsTotal := int(0.5 + d.Seconds()) + minutes := secondsTotal / 60 + seconds := secondsTotal - minutes*60 + + var timeString string + if minutes > 0 { + timeString = fmt.Sprintf("%dm%02ds", minutes, seconds) + } else { + timeString = fmt.Sprintf("%ds", seconds) + } + + if isNegative { + return fmt.Sprintf("[rate limit was reset %v ago]", timeString) + } + return fmt.Sprintf("[rate reset in %v]", timeString) +} + +// When using roundTripWithOptionalFollowRedirect, note that it +// is the responsibility of the caller to close the response body. +func (c *Client) roundTripWithOptionalFollowRedirect(ctx context.Context, u string, followRedirects bool) (*http.Response, error) { + req, err := c.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + + var resp *http.Response + // Use http.DefaultTransport if no custom Transport is configured + req = withContext(ctx, req) + if c.client.Transport == nil { + resp, err = http.DefaultTransport.RoundTrip(req) + } else { + resp, err = c.client.Transport.RoundTrip(req) + } + if err != nil { + return nil, err + } + + // If redirect response is returned, follow it + if followRedirects && resp.StatusCode == http.StatusMovedPermanently { + resp.Body.Close() + u = resp.Header.Get("Location") + resp, err = c.roundTripWithOptionalFollowRedirect(ctx, u, false) + } + return resp, err +} + +// Bool is a helper routine that allocates a new bool value +// to store v and returns a pointer to it. +func Bool(v bool) *bool { return &v } + +// Int is a helper routine that allocates a new int value +// to store v and returns a pointer to it. +func Int(v int) *int { return &v } + +// Int64 is a helper routine that allocates a new int64 value +// to store v and returns a pointer to it. +func Int64(v int64) *int64 { return &v } + +// String is a helper routine that allocates a new string value +// to store v and returns a pointer to it. +func String(v string) *string { return &v } diff --git a/vendor/github.com/google/go-github/v45/github/gitignore.go b/vendor/github.com/google/go-github/v45/github/gitignore.go new file mode 100644 index 0000000000..a20a868b44 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/gitignore.go @@ -0,0 +1,64 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GitignoresService provides access to the gitignore related functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/gitignore/ +type GitignoresService service + +// Gitignore represents a .gitignore file as returned by the GitHub API. +type Gitignore struct { + Name *string `json:"name,omitempty"` + Source *string `json:"source,omitempty"` +} + +func (g Gitignore) String() string { + return Stringify(g) +} + +// List all available Gitignore templates. +// +// GitHub API docs: https://docs.github.com/en/rest/gitignore/#listing-available-templates +func (s *GitignoresService) List(ctx context.Context) ([]string, *Response, error) { + req, err := s.client.NewRequest("GET", "gitignore/templates", nil) + if err != nil { + return nil, nil, err + } + + var availableTemplates []string + resp, err := s.client.Do(ctx, req, &availableTemplates) + if err != nil { + return nil, resp, err + } + + return availableTemplates, resp, nil +} + +// Get a Gitignore by name. +// +// GitHub API docs: https://docs.github.com/en/rest/gitignore#get-a-gitignore-template +func (s *GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) { + u := fmt.Sprintf("gitignore/templates/%v", name) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + gitignore := new(Gitignore) + resp, err := s.client.Do(ctx, req, gitignore) + if err != nil { + return nil, resp, err + } + + return gitignore, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/interactions.go b/vendor/github.com/google/go-github/v45/github/interactions.go new file mode 100644 index 0000000000..a690f61268 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/interactions.go @@ -0,0 +1,28 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// InteractionsService handles communication with the repository and organization related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/interactions/ +type InteractionsService service + +// InteractionRestriction represents the interaction restrictions for repository and organization. +type InteractionRestriction struct { + // Specifies the group of GitHub users who can + // comment, open issues, or create pull requests for the given repository. + // Possible values are: "existing_users", "contributors_only" and "collaborators_only". + Limit *string `json:"limit,omitempty"` + + // Origin specifies the type of the resource to interact with. + // Possible values are: "repository" and "organization". + Origin *string `json:"origin,omitempty"` + + // ExpiresAt specifies the time after which the interaction restrictions expire. + // The default expiry time is 24 hours from the time restriction is created. + ExpiresAt *Timestamp `json:"expires_at,omitempty"` +} diff --git a/vendor/github.com/google/go-github/v45/github/interactions_orgs.go b/vendor/github.com/google/go-github/v45/github/interactions_orgs.go new file mode 100644 index 0000000000..5c7663f583 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/interactions_orgs.go @@ -0,0 +1,80 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetRestrictionsForOrg fetches the interaction restrictions for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/interactions/orgs#get-interaction-restrictions-for-an-organization +func (s *InteractionsService) GetRestrictionsForOrg(ctx context.Context, organization string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + organizationInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, organizationInteractions) + if err != nil { + return nil, resp, err + } + + return organizationInteractions, resp, nil +} + +// UpdateRestrictionsForOrg adds or updates the interaction restrictions for an organization. +// +// limit specifies the group of GitHub users who can comment, open issues, or create pull requests +// in public repositories for the given organization. +// Possible values are: "existing_users", "contributors_only", "collaborators_only". +// +// GitHub API docs: https://docs.github.com/en/rest/interactions/orgs#set-interaction-restrictions-for-an-organization +func (s *InteractionsService) UpdateRestrictionsForOrg(ctx context.Context, organization, limit string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + + interaction := &InteractionRestriction{Limit: String(limit)} + + req, err := s.client.NewRequest("PUT", u, interaction) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + organizationInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, organizationInteractions) + if err != nil { + return nil, resp, err + } + + return organizationInteractions, resp, nil +} + +// RemoveRestrictionsFromOrg removes the interaction restrictions for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/interactions/orgs#remove-interaction-restrictions-for-an-organization +func (s *InteractionsService) RemoveRestrictionsFromOrg(ctx context.Context, organization string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/interaction-limits", organization) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/interactions_repos.go b/vendor/github.com/google/go-github/v45/github/interactions_repos.go new file mode 100644 index 0000000000..41e6c5319d --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/interactions_repos.go @@ -0,0 +1,80 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetRestrictionsForRepo fetches the interaction restrictions for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/interactions/repos#get-interaction-restrictions-for-a-repository +func (s *InteractionsService) GetRestrictionsForRepo(ctx context.Context, owner, repo string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + repositoryInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, repositoryInteractions) + if err != nil { + return nil, resp, err + } + + return repositoryInteractions, resp, nil +} + +// UpdateRestrictionsForRepo adds or updates the interaction restrictions for a repository. +// +// limit specifies the group of GitHub users who can comment, open issues, or create pull requests +// for the given repository. +// Possible values are: "existing_users", "contributors_only", "collaborators_only". +// +// GitHub API docs: https://docs.github.com/en/rest/interactions/repos#set-interaction-restrictions-for-a-repository +func (s *InteractionsService) UpdateRestrictionsForRepo(ctx context.Context, owner, repo, limit string) (*InteractionRestriction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + + interaction := &InteractionRestriction{Limit: String(limit)} + + req, err := s.client.NewRequest("PUT", u, interaction) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + repositoryInteractions := new(InteractionRestriction) + + resp, err := s.client.Do(ctx, req, repositoryInteractions) + if err != nil { + return nil, resp, err + } + + return repositoryInteractions, resp, nil +} + +// RemoveRestrictionsFromRepo removes the interaction restrictions for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/interactions/repos#remove-interaction-restrictions-for-a-repository +func (s *InteractionsService) RemoveRestrictionsFromRepo(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/issue_import.go b/vendor/github.com/google/go-github/v45/github/issue_import.go new file mode 100644 index 0000000000..a9810407cc --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/issue_import.go @@ -0,0 +1,152 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "time" +) + +// IssueImportService handles communication with the issue import related +// methods of the Issue Import GitHub API. +type IssueImportService service + +// IssueImportRequest represents a request to create an issue. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#supported-issue-and-comment-fields +type IssueImportRequest struct { + IssueImport IssueImport `json:"issue"` + Comments []*Comment `json:"comments,omitempty"` +} + +// IssueImport represents body of issue to import. +type IssueImport struct { + Title string `json:"title"` + Body string `json:"body"` + CreatedAt *time.Time `json:"created_at,omitempty"` + ClosedAt *time.Time `json:"closed_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Assignee *string `json:"assignee,omitempty"` + Milestone *int `json:"milestone,omitempty"` + Closed *bool `json:"closed,omitempty"` + Labels []string `json:"labels,omitempty"` +} + +// Comment represents comments of issue to import. +type Comment struct { + CreatedAt *time.Time `json:"created_at,omitempty"` + Body string `json:"body"` +} + +// IssueImportResponse represents the response of an issue import create request. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#import-issue-response +type IssueImportResponse struct { + ID *int `json:"id,omitempty"` + Status *string `json:"status,omitempty"` + URL *string `json:"url,omitempty"` + ImportIssuesURL *string `json:"import_issues_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Message *string `json:"message,omitempty"` + DocumentationURL *string `json:"documentation_url,omitempty"` + Errors []*IssueImportError `json:"errors,omitempty"` +} + +// IssueImportError represents errors of an issue import create request. +type IssueImportError struct { + Location *string `json:"location,omitempty"` + Resource *string `json:"resource,omitempty"` + Field *string `json:"field,omitempty"` + Value *string `json:"value,omitempty"` + Code *string `json:"code,omitempty"` +} + +// Create a new imported issue on the specified repository. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#start-an-issue-import +func (s *IssueImportService) Create(ctx context.Context, owner, repo string, issue *IssueImportRequest) (*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues", owner, repo) + req, err := s.client.NewRequest("POST", u, issue) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + i := new(IssueImportResponse) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + aerr, ok := err.(*AcceptedError) + if ok { + decErr := json.Unmarshal(aerr.Raw, i) + if decErr != nil { + err = decErr + } + + return i, resp, nil + } + + return nil, resp, err + } + + return i, resp, nil +} + +// CheckStatus checks the status of an imported issue. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#import-status-request +func (s *IssueImportService) CheckStatus(ctx context.Context, owner, repo string, issueID int64) (*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues/%v", owner, repo, issueID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + i := new(IssueImportResponse) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// CheckStatusSince checks the status of multiple imported issues since a given date. +// +// https://gist.github.com/jonmagic/5282384165e0f86ef105#check-status-of-multiple-issues +func (s *IssueImportService) CheckStatusSince(ctx context.Context, owner, repo string, since time.Time) ([]*IssueImportResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/issues?since=%v", owner, repo, since.Format("2006-01-02")) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeIssueImportAPI) + + var b bytes.Buffer + resp, err := s.client.Do(ctx, req, &b) + if err != nil { + return nil, resp, err + } + + var i []*IssueImportResponse + err = json.Unmarshal(b.Bytes(), &i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/issues.go b/vendor/github.com/google/go-github/v45/github/issues.go new file mode 100644 index 0000000000..12488f9815 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/issues.go @@ -0,0 +1,358 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// IssuesService handles communication with the issue related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/ +type IssuesService service + +// Issue represents a GitHub issue on a repository. +// +// Note: As far as the GitHub API is concerned, every pull request is an issue, +// but not every issue is a pull request. Some endpoints, events, and webhooks +// may also return pull requests via this struct. If PullRequestLinks is nil, +// this is an issue, and if PullRequestLinks is not nil, this is a pull request. +// The IsPullRequest helper method can be used to check that. +type Issue struct { + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + User *User `json:"user,omitempty"` + Labels []*Label `json:"labels,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Comments *int `json:"comments,omitempty"` + ClosedAt *time.Time `json:"closed_at,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + ClosedBy *User `json:"closed_by,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"` + Repository *Repository `json:"repository,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + NodeID *string `json:"node_id,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://docs.github.com/en/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` + + // ActiveLockReason is populated only when LockReason is provided while locking the issue. + // Possible values are: "off-topic", "too heated", "resolved", and "spam". + ActiveLockReason *string `json:"active_lock_reason,omitempty"` +} + +func (i Issue) String() string { + return Stringify(i) +} + +// IsPullRequest reports whether the issue is also a pull request. It uses the +// method recommended by GitHub's API documentation, which is to check whether +// PullRequestLinks is non-nil. +func (i Issue) IsPullRequest() bool { + return i.PullRequestLinks != nil +} + +// IssueRequest represents a request to create/edit an issue. +// It is separate from Issue above because otherwise Labels +// and Assignee fail to serialize to the correct JSON. +type IssueRequest struct { + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + Labels *[]string `json:"labels,omitempty"` + Assignee *string `json:"assignee,omitempty"` + State *string `json:"state,omitempty"` + Milestone *int `json:"milestone,omitempty"` + Assignees *[]string `json:"assignees,omitempty"` +} + +// IssueListOptions specifies the optional parameters to the IssuesService.List +// and IssuesService.ListByOrg methods. +type IssueListOptions struct { + // Filter specifies which issues to list. Possible values are: assigned, + // created, mentioned, subscribed, all. Default is "assigned". + Filter string `url:"filter,omitempty"` + + // State filters issues based on their state. Possible values are: open, + // closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Labels filters issues based on their label. + Labels []string `url:"labels,comma,omitempty"` + + // Sort specifies how to sort issues. Possible values are: created, updated, + // and comments. Default value is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort issues. Possible values are: asc, desc. + // Default is "desc". + Direction string `url:"direction,omitempty"` + + // Since filters issues by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// PullRequestLinks object is added to the Issue object when it's an issue included +// in the IssueCommentEvent webhook payload, if the webhook is fired by a comment on a PR. +type PullRequestLinks struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` +} + +// List the issues for the authenticated user. If all is true, list issues +// across all the user's visible repositories including owned, member, and +// organization repositories; if false, list only owned and member +// repositories. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#list-user-account-issues-assigned-to-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#list-issues-assigned-to-the-authenticated-user +func (s *IssuesService) List(ctx context.Context, all bool, opts *IssueListOptions) ([]*Issue, *Response, error) { + var u string + if all { + u = "issues" + } else { + u = "user/issues" + } + return s.listIssues(ctx, u, opts) +} + +// ListByOrg fetches the issues in the specified organization for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#list-organization-issues-assigned-to-the-authenticated-user +func (s *IssuesService) ListByOrg(ctx context.Context, org string, opts *IssueListOptions) ([]*Issue, *Response, error) { + u := fmt.Sprintf("orgs/%v/issues", org) + return s.listIssues(ctx, u, opts) +} + +func (s *IssuesService) listIssues(ctx context.Context, u string, opts *IssueListOptions) ([]*Issue, *Response, error) { + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var issues []*Issue + resp, err := s.client.Do(ctx, req, &issues) + if err != nil { + return nil, resp, err + } + + return issues, resp, nil +} + +// IssueListByRepoOptions specifies the optional parameters to the +// IssuesService.ListByRepo method. +type IssueListByRepoOptions struct { + // Milestone limits issues for the specified milestone. Possible values are + // a milestone number, "none" for issues with no milestone, "*" for issues + // with any milestone. + Milestone string `url:"milestone,omitempty"` + + // State filters issues based on their state. Possible values are: open, + // closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Assignee filters issues based on their assignee. Possible values are a + // user name, "none" for issues that are not assigned, "*" for issues with + // any assigned user. + Assignee string `url:"assignee,omitempty"` + + // Creator filters issues based on their creator. + Creator string `url:"creator,omitempty"` + + // Mentioned filters issues to those mentioned a specific user. + Mentioned string `url:"mentioned,omitempty"` + + // Labels filters issues based on their label. + Labels []string `url:"labels,omitempty,comma"` + + // Sort specifies how to sort issues. Possible values are: created, updated, + // and comments. Default value is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort issues. Possible values are: asc, desc. + // Default is "desc". + Direction string `url:"direction,omitempty"` + + // Since filters issues by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListByRepo lists the issues for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#list-repository-issues +func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opts *IssueListByRepoOptions) ([]*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var issues []*Issue + resp, err := s.client.Do(ctx, req, &issues) + if err != nil { + return nil, resp, err + } + + return issues, resp, nil +} + +// Get a single issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#get-an-issue +func (s *IssuesService) Get(ctx context.Context, owner string, repo string, number int) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + issue := new(Issue) + resp, err := s.client.Do(ctx, req, issue) + if err != nil { + return nil, resp, err + } + + return issue, resp, nil +} + +// Create a new issue on the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#create-an-issue +func (s *IssuesService) Create(ctx context.Context, owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues", owner, repo) + req, err := s.client.NewRequest("POST", u, issue) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// Edit (update) an issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#update-an-issue +func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number) + req, err := s.client.NewRequest("PATCH", u, issue) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// Remove a milestone from an issue. +// +// This is a helper method to explicitly update an issue with a `null` milestone, thereby removing it. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#update-an-issue +func (s *IssuesService) RemoveMilestone(ctx context.Context, owner, repo string, issueNumber int) (*Issue, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v", owner, repo, issueNumber) + req, err := s.client.NewRequest("PATCH", u, &struct { + Milestone *Milestone `json:"milestone"` + }{}) + if err != nil { + return nil, nil, err + } + + i := new(Issue) + resp, err := s.client.Do(ctx, req, i) + if err != nil { + return nil, resp, err + } + + return i, resp, nil +} + +// LockIssueOptions specifies the optional parameters to the +// IssuesService.Lock method. +type LockIssueOptions struct { + // LockReason specifies the reason to lock this issue. + // Providing a lock reason can help make it clearer to contributors why an issue + // was locked. Possible values are: "off-topic", "too heated", "resolved", and "spam". + LockReason string `json:"lock_reason,omitempty"` +} + +// Lock an issue's conversation. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#lock-an-issue +func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opts *LockIssueOptions) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unlock an issue's conversation. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/issues#unlock-an-issue +func (s *IssuesService) Unlock(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/issues_assignees.go b/vendor/github.com/google/go-github/v45/github/issues_assignees.go new file mode 100644 index 0000000000..b7f2e80243 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/issues_assignees.go @@ -0,0 +1,95 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListAssignees fetches all available assignees (owners and collaborators) to +// which issues may be assigned. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/assignees#list-assignees +func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var assignees []*User + resp, err := s.client.Do(ctx, req, &assignees) + if err != nil { + return nil, resp, err + } + + return assignees, resp, nil +} + +// IsAssignee checks if a user is an assignee for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/assignees#check-if-a-user-can-be-assigned +func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + assignee, err := parseBoolResponse(err) + return assignee, resp, err +} + +// AddAssignees adds the provided GitHub users as assignees to the issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/assignees#add-assignees-to-an-issue +func (s *IssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { + users := &struct { + Assignees []string `json:"assignees,omitempty"` + }{Assignees: assignees} + u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) + req, err := s.client.NewRequest("POST", u, users) + if err != nil { + return nil, nil, err + } + + issue := &Issue{} + resp, err := s.client.Do(ctx, req, issue) + if err != nil { + return nil, resp, err + } + + return issue, resp, nil +} + +// RemoveAssignees removes the provided GitHub users as assignees from the issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/assignees#remove-assignees-from-an-issue +func (s *IssuesService) RemoveAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) { + users := &struct { + Assignees []string `json:"assignees,omitempty"` + }{Assignees: assignees} + u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, users) + if err != nil { + return nil, nil, err + } + + issue := &Issue{} + resp, err := s.client.Do(ctx, req, issue) + if err != nil { + return nil, resp, err + } + + return issue, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/issues_comments.go b/vendor/github.com/google/go-github/v45/github/issues_comments.go new file mode 100644 index 0000000000..361ee49a69 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/issues_comments.go @@ -0,0 +1,154 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// IssueComment represents a comment left on an issue. +type IssueComment struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Body *string `json:"body,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + // AuthorAssociation is the comment author's relationship to the issue's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` +} + +func (i IssueComment) String() string { + return Stringify(i) +} + +// IssueListCommentsOptions specifies the optional parameters to the +// IssuesService.ListComments method. +type IssueListCommentsOptions struct { + // Sort specifies how to sort comments. Possible values are: created, updated. + Sort *string `url:"sort,omitempty"` + + // Direction in which to sort comments. Possible values are: asc, desc. + Direction *string `url:"direction,omitempty"` + + // Since filters comments by time. + Since *time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListComments lists all comments on the specified issue. Specifying an issue +// number of 0 will return all comments on all issues for the repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/comments#list-issue-comments +// GitHub API docs: https://docs.github.com/en/rest/issues/comments#list-issue-comments-for-a-repository +func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions) ([]*IssueComment, *Response, error) { + var u string + if number == 0 { + u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo) + } else { + u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*IssueComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment fetches the specified issue comment. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/comments#get-an-issue-comment +func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + comment := new(IssueComment) + resp, err := s.client.Do(ctx, req, comment) + if err != nil { + return nil, resp, err + } + + return comment, resp, nil +} + +// CreateComment creates a new comment on the specified issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/comments#create-an-issue-comment +func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + c := new(IssueComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment updates an issue comment. +// A non-nil comment.Body must be provided. Other comment fields should be left nil. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/comments#update-an-issue-comment +func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + c := new(IssueComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes an issue comment. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/comments#delete-an-issue-comment +func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/issues_events.go b/vendor/github.com/google/go-github/v45/github/issues_events.go new file mode 100644 index 0000000000..d8ffc0b542 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/issues_events.go @@ -0,0 +1,179 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// IssueEvent represents an event that occurred around an Issue or Pull Request. +type IssueEvent struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + + // The User that generated this event. + Actor *User `json:"actor,omitempty"` + + // Event identifies the actual type of Event that occurred. Possible + // values are: + // + // closed + // The Actor closed the issue. + // If the issue was closed by commit message, CommitID holds the SHA1 hash of the commit. + // + // merged + // The Actor merged into master a branch containing a commit mentioning the issue. + // CommitID holds the SHA1 of the merge commit. + // + // referenced + // The Actor committed to master a commit mentioning the issue in its commit message. + // CommitID holds the SHA1 of the commit. + // + // reopened, unlocked + // The Actor did that to the issue. + // + // locked + // The Actor locked the issue. + // LockReason holds the reason of locking the issue (if provided while locking). + // + // renamed + // The Actor changed the issue title from Rename.From to Rename.To. + // + // mentioned + // Someone unspecified @mentioned the Actor [sic] in an issue comment body. + // + // assigned, unassigned + // The Assigner assigned the issue to or removed the assignment from the Assignee. + // + // labeled, unlabeled + // The Actor added or removed the Label from the issue. + // + // milestoned, demilestoned + // The Actor added or removed the issue from the Milestone. + // + // subscribed, unsubscribed + // The Actor subscribed to or unsubscribed from notifications for an issue. + // + // head_ref_deleted, head_ref_restored + // The pull request’s branch was deleted or restored. + // + // review_dismissed + // The review was dismissed and `DismissedReview` will be populated below. + // + // review_requested, review_request_removed + // The Actor requested or removed the request for a review. + // RequestedReviewer and ReviewRequester will be populated below. + // + Event *string `json:"event,omitempty"` + + CreatedAt *time.Time `json:"created_at,omitempty"` + Issue *Issue `json:"issue,omitempty"` + + // Only present on certain events; see above. + Assignee *User `json:"assignee,omitempty"` + Assigner *User `json:"assigner,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + Label *Label `json:"label,omitempty"` + Rename *Rename `json:"rename,omitempty"` + LockReason *string `json:"lock_reason,omitempty"` + ProjectCard *ProjectCard `json:"project_card,omitempty"` + DismissedReview *DismissedReview `json:"dismissed_review,omitempty"` + RequestedReviewer *User `json:"requested_reviewer,omitempty"` + ReviewRequester *User `json:"review_requester,omitempty"` +} + +// DismissedReview represents details for 'dismissed_review' events. +type DismissedReview struct { + // State represents the state of the dismissed review. + // Possible values are: "commented", "approved", and "changes_requested". + State *string `json:"state,omitempty"` + ReviewID *int64 `json:"review_id,omitempty"` + DismissalMessage *string `json:"dismissal_message,omitempty"` + DismissalCommitID *string `json:"dismissal_commit_id,omitempty"` +} + +// ListIssueEvents lists events for the specified issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/events#list-issue-events +func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeProjectCardDetailsPreview) + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// ListRepositoryEvents lists events for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/events#list-issue-events-for-a-repository +func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var events []*IssueEvent + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} + +// GetEvent returns the specified issue event. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/events#get-an-issue-event +func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + event := new(IssueEvent) + resp, err := s.client.Do(ctx, req, event) + if err != nil { + return nil, resp, err + } + + return event, resp, nil +} + +// Rename contains details for 'renamed' events. +type Rename struct { + From *string `json:"from,omitempty"` + To *string `json:"to,omitempty"` +} + +func (r Rename) String() string { + return Stringify(r) +} diff --git a/vendor/github.com/google/go-github/v45/github/issues_labels.go b/vendor/github.com/google/go-github/v45/github/issues_labels.go new file mode 100644 index 0000000000..d0f865c03f --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/issues_labels.go @@ -0,0 +1,231 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Label represents a GitHub label on an Issue +type Label struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Color *string `json:"color,omitempty"` + Description *string `json:"description,omitempty"` + Default *bool `json:"default,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (l Label) String() string { + return Stringify(l) +} + +// ListLabels lists all labels for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#list-labels-for-a-repository +func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} + +// GetLabel gets a single label. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#get-a-label +func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + label := new(Label) + resp, err := s.client.Do(ctx, req, label) + if err != nil { + return nil, resp, err + } + + return label, resp, nil +} + +// CreateLabel creates a new label on the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#create-a-label +func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo string, label *Label) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels", owner, repo) + req, err := s.client.NewRequest("POST", u, label) + if err != nil { + return nil, nil, err + } + + l := new(Label) + resp, err := s.client.Do(ctx, req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// EditLabel edits a label. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#update-a-label +func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string, name string, label *Label) (*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("PATCH", u, label) + if err != nil { + return nil, nil, err + } + + l := new(Label) + resp, err := s.client.Do(ctx, req, l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// DeleteLabel deletes a label. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#delete-a-label +func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo string, name string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListLabelsByIssue lists all labels for an issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#list-labels-for-an-issue +func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} + +// AddLabelsToIssue adds labels to an issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#add-labels-to-an-issue +func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("POST", u, labels) + if err != nil { + return nil, nil, err + } + + var l []*Label + resp, err := s.client.Do(ctx, req, &l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// RemoveLabelForIssue removes a label for an issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#remove-a-label-from-an-issue +func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels/%v", owner, repo, number, label) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ReplaceLabelsForIssue replaces all labels for an issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#set-labels-for-an-issue +func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("PUT", u, labels) + if err != nil { + return nil, nil, err + } + + var l []*Label + resp, err := s.client.Do(ctx, req, &l) + if err != nil { + return nil, resp, err + } + + return l, resp, nil +} + +// RemoveLabelsForIssue removes all labels for an issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#remove-all-labels-from-an-issue +func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListLabelsForMilestone lists labels for every issue in a milestone. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/labels#list-labels-for-issues-in-a-milestone +func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var labels []*Label + resp, err := s.client.Do(ctx, req, &labels) + if err != nil { + return nil, resp, err + } + + return labels, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/issues_milestones.go b/vendor/github.com/google/go-github/v45/github/issues_milestones.go new file mode 100644 index 0000000000..3c9be2407e --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/issues_milestones.go @@ -0,0 +1,148 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// Milestone represents a GitHub repository milestone. +type Milestone struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Title *string `json:"title,omitempty"` + Description *string `json:"description,omitempty"` + Creator *User `json:"creator,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` + ClosedIssues *int `json:"closed_issues,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + ClosedAt *time.Time `json:"closed_at,omitempty"` + DueOn *time.Time `json:"due_on,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (m Milestone) String() string { + return Stringify(m) +} + +// MilestoneListOptions specifies the optional parameters to the +// IssuesService.ListMilestones method. +type MilestoneListOptions struct { + // State filters milestones based on their state. Possible values are: + // open, closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Sort specifies how to sort milestones. Possible values are: due_on, completeness. + // Default value is "due_on". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort milestones. Possible values are: asc, desc. + // Default is "asc". + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListMilestones lists all milestones for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/milestones#list-milestones +func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opts *MilestoneListOptions) ([]*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var milestones []*Milestone + resp, err := s.client.Do(ctx, req, &milestones) + if err != nil { + return nil, resp, err + } + + return milestones, resp, nil +} + +// GetMilestone gets a single milestone. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/milestones#get-a-milestone +func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + milestone := new(Milestone) + resp, err := s.client.Do(ctx, req, milestone) + if err != nil { + return nil, resp, err + } + + return milestone, resp, nil +} + +// CreateMilestone creates a new milestone on the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/milestones#create-a-milestone +func (s *IssuesService) CreateMilestone(ctx context.Context, owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo) + req, err := s.client.NewRequest("POST", u, milestone) + if err != nil { + return nil, nil, err + } + + m := new(Milestone) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// EditMilestone edits a milestone. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/milestones#update-a-milestone +func (s *IssuesService) EditMilestone(ctx context.Context, owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("PATCH", u, milestone) + if err != nil { + return nil, nil, err + } + + m := new(Milestone) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteMilestone deletes a milestone. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/milestones#delete-a-milestone +func (s *IssuesService) DeleteMilestone(ctx context.Context, owner string, repo string, number int) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/issues_timeline.go b/vendor/github.com/google/go-github/v45/github/issues_timeline.go new file mode 100644 index 0000000000..9ec498e45c --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/issues_timeline.go @@ -0,0 +1,188 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" + "time" +) + +// Timeline represents an event that occurred around an Issue or Pull Request. +// +// It is similar to an IssueEvent but may contain more information. +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/events/issue-event-types +type Timeline struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + CommitURL *string `json:"commit_url,omitempty"` + + // The User object that generated the event. + Actor *User `json:"actor,omitempty"` + + // The person who commented on the issue. + User *User `json:"user,omitempty"` + + // The person who authored the commit. + Author *CommitAuthor `json:"author,omitempty"` + // The person who committed the commit on behalf of the author. + Committer *CommitAuthor `json:"committer,omitempty"` + // The SHA of the commit in the pull request. + SHA *string `json:"sha,omitempty"` + // The commit message. + Message *string `json:"message,omitempty"` + + // Event identifies the actual type of Event that occurred. Possible values + // are: + // + // assigned + // The issue was assigned to the assignee. + // + // closed + // The issue was closed by the actor. When the commit_id is present, it + // identifies the commit that closed the issue using "closes / fixes #NN" + // syntax. + // + // commented + // A comment was added to the issue. + // + // committed + // A commit was added to the pull request's 'HEAD' branch. Only provided + // for pull requests. + // + // cross-referenced + // The issue was referenced from another issue. The 'source' attribute + // contains the 'id', 'actor', and 'url' of the reference's source. + // + // demilestoned + // The issue was removed from a milestone. + // + // head_ref_deleted + // The pull request's branch was deleted. + // + // head_ref_restored + // The pull request's branch was restored. + // + // labeled + // A label was added to the issue. + // + // locked + // The issue was locked by the actor. + // + // mentioned + // The actor was @mentioned in an issue body. + // + // merged + // The issue was merged by the actor. The 'commit_id' attribute is the + // SHA1 of the HEAD commit that was merged. + // + // milestoned + // The issue was added to a milestone. + // + // referenced + // The issue was referenced from a commit message. The 'commit_id' + // attribute is the commit SHA1 of where that happened. + // + // renamed + // The issue title was changed. + // + // reopened + // The issue was reopened by the actor. + // + // reviewed + // The pull request was reviewed. + // + // subscribed + // The actor subscribed to receive notifications for an issue. + // + // unassigned + // The assignee was unassigned from the issue. + // + // unlabeled + // A label was removed from the issue. + // + // unlocked + // The issue was unlocked by the actor. + // + // unsubscribed + // The actor unsubscribed to stop receiving notifications for an issue. + // + Event *string `json:"event,omitempty"` + + // The string SHA of a commit that referenced this Issue or Pull Request. + CommitID *string `json:"commit_id,omitempty"` + // The timestamp indicating when the event occurred. + CreatedAt *time.Time `json:"created_at,omitempty"` + // The Label object including `name` and `color` attributes. Only provided for + // 'labeled' and 'unlabeled' events. + Label *Label `json:"label,omitempty"` + // The User object which was assigned to (or unassigned from) this Issue or + // Pull Request. Only provided for 'assigned' and 'unassigned' events. + Assignee *User `json:"assignee,omitempty"` + Assigner *User `json:"assigner,omitempty"` + + // The Milestone object including a 'title' attribute. + // Only provided for 'milestoned' and 'demilestoned' events. + Milestone *Milestone `json:"milestone,omitempty"` + // The 'id', 'actor', and 'url' for the source of a reference from another issue. + // Only provided for 'cross-referenced' events. + Source *Source `json:"source,omitempty"` + // An object containing rename details including 'from' and 'to' attributes. + // Only provided for 'renamed' events. + Rename *Rename `json:"rename,omitempty"` + ProjectCard *ProjectCard `json:"project_card,omitempty"` + // The state of a submitted review. Can be one of: 'commented', + // 'changes_requested' or 'approved'. + // Only provided for 'reviewed' events. + State *string `json:"state,omitempty"` + + // The person requested to review the pull request. + Reviewer *User `json:"requested_reviewer,omitempty"` + // The person who requested a review. + Requester *User `json:"review_requester,omitempty"` + + // The review summary text. + Body *string `json:"body,omitempty"` + SubmittedAt *time.Time `json:"submitted_at,omitempty"` +} + +// Source represents a reference's source. +type Source struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Actor *User `json:"actor,omitempty"` + Type *string `json:"type,omitempty"` + Issue *Issue `json:"issue,omitempty"` +} + +// ListIssueTimeline lists events for the specified issue. +// +// GitHub API docs: https://docs.github.com/en/rest/issues/timeline#list-timeline-events-for-an-issue +func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Timeline, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeTimelinePreview, mediaTypeProjectCardDetailsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var events []*Timeline + resp, err := s.client.Do(ctx, req, &events) + if err != nil { + return nil, resp, err + } + + return events, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/licenses.go b/vendor/github.com/google/go-github/v45/github/licenses.go new file mode 100644 index 0000000000..0877b6d183 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/licenses.go @@ -0,0 +1,97 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// LicensesService handles communication with the license related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/licenses/ +type LicensesService service + +// RepositoryLicense represents the license for a repository. +type RepositoryLicense struct { + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + + SHA *string `json:"sha,omitempty"` + Size *int `json:"size,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` + Type *string `json:"type,omitempty"` + Content *string `json:"content,omitempty"` + Encoding *string `json:"encoding,omitempty"` + License *License `json:"license,omitempty"` +} + +func (l RepositoryLicense) String() string { + return Stringify(l) +} + +// License represents an open source license. +type License struct { + Key *string `json:"key,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + + SPDXID *string `json:"spdx_id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Featured *bool `json:"featured,omitempty"` + Description *string `json:"description,omitempty"` + Implementation *string `json:"implementation,omitempty"` + Permissions *[]string `json:"permissions,omitempty"` + Conditions *[]string `json:"conditions,omitempty"` + Limitations *[]string `json:"limitations,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (l License) String() string { + return Stringify(l) +} + +// List popular open source licenses. +// +// GitHub API docs: https://docs.github.com/en/rest/licenses/#list-all-licenses +func (s *LicensesService) List(ctx context.Context) ([]*License, *Response, error) { + req, err := s.client.NewRequest("GET", "licenses", nil) + if err != nil { + return nil, nil, err + } + + var licenses []*License + resp, err := s.client.Do(ctx, req, &licenses) + if err != nil { + return nil, resp, err + } + + return licenses, resp, nil +} + +// Get extended metadata for one license. +// +// GitHub API docs: https://docs.github.com/en/rest/licenses#get-a-license +func (s *LicensesService) Get(ctx context.Context, licenseName string) (*License, *Response, error) { + u := fmt.Sprintf("licenses/%s", licenseName) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + license := new(License) + resp, err := s.client.Do(ctx, req, license) + if err != nil { + return nil, resp, err + } + + return license, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/messages.go b/vendor/github.com/google/go-github/v45/github/messages.go new file mode 100644 index 0000000000..44477ddb0d --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/messages.go @@ -0,0 +1,306 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file provides functions for validating payloads from GitHub Webhooks. +// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github + +package github + +import ( + "crypto/hmac" + "crypto/sha1" + "crypto/sha256" + "crypto/sha512" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "hash" + "io" + "io/ioutil" + "mime" + "net/http" + "net/url" + "strings" +) + +const ( + // sha1Prefix is the prefix used by GitHub before the HMAC hexdigest. + sha1Prefix = "sha1" + // sha256Prefix and sha512Prefix are provided for future compatibility. + sha256Prefix = "sha256" + sha512Prefix = "sha512" + // SHA1SignatureHeader is the GitHub header key used to pass the HMAC-SHA1 hexdigest. + SHA1SignatureHeader = "X-Hub-Signature" + // SHA256SignatureHeader is the GitHub header key used to pass the HMAC-SHA256 hexdigest. + SHA256SignatureHeader = "X-Hub-Signature-256" + // EventTypeHeader is the GitHub header key used to pass the event type. + EventTypeHeader = "X-Github-Event" + // DeliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event. + DeliveryIDHeader = "X-Github-Delivery" +) + +var ( + // eventTypeMapping maps webhooks types to their corresponding go-github struct types. + eventTypeMapping = map[string]string{ + "branch_protection_rule": "BranchProtectionRuleEvent", + "check_run": "CheckRunEvent", + "check_suite": "CheckSuiteEvent", + "commit_comment": "CommitCommentEvent", + "content_reference": "ContentReferenceEvent", + "create": "CreateEvent", + "delete": "DeleteEvent", + "deploy_key": "DeployKeyEvent", + "deployment": "DeploymentEvent", + "deployment_status": "DeploymentStatusEvent", + "discussion": "DiscussionEvent", + "fork": "ForkEvent", + "github_app_authorization": "GitHubAppAuthorizationEvent", + "gollum": "GollumEvent", + "installation": "InstallationEvent", + "installation_repositories": "InstallationRepositoriesEvent", + "issue_comment": "IssueCommentEvent", + "issues": "IssuesEvent", + "label": "LabelEvent", + "marketplace_purchase": "MarketplacePurchaseEvent", + "member": "MemberEvent", + "membership": "MembershipEvent", + "meta": "MetaEvent", + "milestone": "MilestoneEvent", + "organization": "OrganizationEvent", + "org_block": "OrgBlockEvent", + "package": "PackageEvent", + "page_build": "PageBuildEvent", + "ping": "PingEvent", + "project": "ProjectEvent", + "project_card": "ProjectCardEvent", + "project_column": "ProjectColumnEvent", + "public": "PublicEvent", + "pull_request": "PullRequestEvent", + "pull_request_review": "PullRequestReviewEvent", + "pull_request_review_comment": "PullRequestReviewCommentEvent", + "pull_request_review_thread": "PullRequestReviewThreadEvent", + "pull_request_target": "PullRequestTargetEvent", + "push": "PushEvent", + "repository": "RepositoryEvent", + "repository_dispatch": "RepositoryDispatchEvent", + "repository_import": "RepositoryImportEvent", + "repository_vulnerability_alert": "RepositoryVulnerabilityAlertEvent", + "release": "ReleaseEvent", + "secret_scanning_alert": "SecretScanningAlertEvent", + "star": "StarEvent", + "status": "StatusEvent", + "team": "TeamEvent", + "team_add": "TeamAddEvent", + "user": "UserEvent", + "watch": "WatchEvent", + "workflow_dispatch": "WorkflowDispatchEvent", + "workflow_job": "WorkflowJobEvent", + "workflow_run": "WorkflowRunEvent", + } +) + +// genMAC generates the HMAC signature for a message provided the secret key +// and hashFunc. +func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte { + mac := hmac.New(hashFunc, key) + mac.Write(message) + return mac.Sum(nil) +} + +// checkMAC reports whether messageMAC is a valid HMAC tag for message. +func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool { + expectedMAC := genMAC(message, key, hashFunc) + return hmac.Equal(messageMAC, expectedMAC) +} + +// messageMAC returns the hex-decoded HMAC tag from the signature and its +// corresponding hash function. +func messageMAC(signature string) ([]byte, func() hash.Hash, error) { + if signature == "" { + return nil, nil, errors.New("missing signature") + } + sigParts := strings.SplitN(signature, "=", 2) + if len(sigParts) != 2 { + return nil, nil, fmt.Errorf("error parsing signature %q", signature) + } + + var hashFunc func() hash.Hash + switch sigParts[0] { + case sha1Prefix: + hashFunc = sha1.New + case sha256Prefix: + hashFunc = sha256.New + case sha512Prefix: + hashFunc = sha512.New + default: + return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0]) + } + + buf, err := hex.DecodeString(sigParts[1]) + if err != nil { + return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err) + } + return buf, hashFunc, nil +} + +// ValidatePayload validates an incoming GitHub Webhook event request body +// and returns the (JSON) payload. +// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". +// If the Content-Type is neither then an error is returned. +// secretToken is the GitHub Webhook secret token. +// If your webhook does not contain a secret token, you can pass nil or an empty slice. +// This is intended for local development purposes only and all webhooks should ideally set up a secret token. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// // read signature from request +// signature := "" +// payload, err := github.ValidatePayloadFromBody(r.Header.Get("Content-Type"), r.Body, signature, s.webhookSecretKey) +// if err != nil { ... } +// // Process payload... +// } +func ValidatePayloadFromBody(contentType string, readable io.Reader, signature string, secretToken []byte) (payload []byte, err error) { + var body []byte // Raw body that GitHub uses to calculate the signature. + + switch contentType { + case "application/json": + var err error + if body, err = ioutil.ReadAll(readable); err != nil { + return nil, err + } + + // If the content type is application/json, + // the JSON payload is just the original body. + payload = body + + case "application/x-www-form-urlencoded": + // payloadFormParam is the name of the form parameter that the JSON payload + // will be in if a webhook has its content type set to application/x-www-form-urlencoded. + const payloadFormParam = "payload" + + var err error + if body, err = ioutil.ReadAll(readable); err != nil { + return nil, err + } + + // If the content type is application/x-www-form-urlencoded, + // the JSON payload will be under the "payload" form param. + form, err := url.ParseQuery(string(body)) + if err != nil { + return nil, err + } + payload = []byte(form.Get(payloadFormParam)) + + default: + return nil, fmt.Errorf("webhook request has unsupported Content-Type %q", contentType) + } + + // Only validate the signature if a secret token exists. This is intended for + // local development only and all webhooks should ideally set up a secret token. + if len(secretToken) > 0 { + if err := ValidateSignature(signature, body, secretToken); err != nil { + return nil, err + } + } + + return payload, nil +} + +// ValidatePayload validates an incoming GitHub Webhook event request +// and returns the (JSON) payload. +// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded". +// If the Content-Type is neither then an error is returned. +// secretToken is the GitHub Webhook secret token. +// If your webhook does not contain a secret token, you can pass nil or an empty slice. +// This is intended for local development purposes only and all webhooks should ideally set up a secret token. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// payload, err := github.ValidatePayload(r, s.webhookSecretKey) +// if err != nil { ... } +// // Process payload... +// } +// +func ValidatePayload(r *http.Request, secretToken []byte) (payload []byte, err error) { + signature := r.Header.Get(SHA256SignatureHeader) + if signature == "" { + signature = r.Header.Get(SHA1SignatureHeader) + } + + contentType, _, err := mime.ParseMediaType(r.Header.Get("Content-Type")) + if err != nil { + return nil, err + } + + return ValidatePayloadFromBody(contentType, r.Body, signature, secretToken) +} + +// ValidateSignature validates the signature for the given payload. +// signature is the GitHub hash signature delivered in the X-Hub-Signature header. +// payload is the JSON payload sent by GitHub Webhooks. +// secretToken is the GitHub Webhook secret token. +// +// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github +func ValidateSignature(signature string, payload, secretToken []byte) error { + messageMAC, hashFunc, err := messageMAC(signature) + if err != nil { + return err + } + if !checkMAC(payload, messageMAC, secretToken, hashFunc) { + return errors.New("payload signature check failed") + } + return nil +} + +// WebHookType returns the event type of webhook request r. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/events/github-event-types +func WebHookType(r *http.Request) string { + return r.Header.Get(EventTypeHeader) +} + +// DeliveryID returns the unique delivery ID of webhook request r. +// +// GitHub API docs: https://docs.github.com/en/developers/webhooks-and-events/events/github-event-types +func DeliveryID(r *http.Request) string { + return r.Header.Get(DeliveryIDHeader) +} + +// ParseWebHook parses the event payload. For recognized event types, a +// value of the corresponding struct type will be returned (as returned +// by Event.ParsePayload()). An error will be returned for unrecognized event +// types. +// +// Example usage: +// +// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) { +// payload, err := github.ValidatePayload(r, s.webhookSecretKey) +// if err != nil { ... } +// event, err := github.ParseWebHook(github.WebHookType(r), payload) +// if err != nil { ... } +// switch event := event.(type) { +// case *github.CommitCommentEvent: +// processCommitCommentEvent(event) +// case *github.CreateEvent: +// processCreateEvent(event) +// ... +// } +// } +// +func ParseWebHook(messageType string, payload []byte) (interface{}, error) { + eventType, ok := eventTypeMapping[messageType] + if !ok { + return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType) + } + + event := Event{ + Type: &eventType, + RawPayload: (*json.RawMessage)(&payload), + } + return event.ParsePayload() +} diff --git a/vendor/github.com/google/go-github/v45/github/migrations.go b/vendor/github.com/google/go-github/v45/github/migrations.go new file mode 100644 index 0000000000..67989c0789 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/migrations.go @@ -0,0 +1,228 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "net/http" + "strings" +) + +// MigrationService provides access to the migration related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/migration/ +type MigrationService service + +// Migration represents a GitHub migration (archival). +type Migration struct { + ID *int64 `json:"id,omitempty"` + GUID *string `json:"guid,omitempty"` + // State is the current state of a migration. + // Possible values are: + // "pending" which means the migration hasn't started yet, + // "exporting" which means the migration is in progress, + // "exported" which means the migration finished successfully, or + // "failed" which means the migration failed. + State *string `json:"state,omitempty"` + // LockRepositories indicates whether repositories are locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` + URL *string `json:"url,omitempty"` + CreatedAt *string `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +func (m Migration) String() string { + return Stringify(m) +} + +// MigrationOptions specifies the optional parameters to Migration methods. +type MigrationOptions struct { + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories bool + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments bool +} + +// startMigration represents the body of a StartMigration request. +type startMigration struct { + // Repositories is a slice of repository names to migrate. + Repositories []string `json:"repositories,omitempty"` + + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` +} + +// StartMigration starts the generation of a migration archive. +// repos is a slice of repository names to migrate. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/orgs#start-an-organization-migration +func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opts *MigrationOptions) (*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations", org) + + body := &startMigration{Repositories: repos} + if opts != nil { + body.LockRepositories = Bool(opts.LockRepositories) + body.ExcludeAttachments = Bool(opts.ExcludeAttachments) + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &Migration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// ListMigrations lists the most recent migrations. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/orgs#list-organization-migrations +func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts *ListOptions) ([]*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + var m []*Migration + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// MigrationStatus gets the status of a specific migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/orgs#get-an-organization-migration-status +func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &Migration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// MigrationArchiveURL fetches a migration archive URL. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/orgs#download-an-organization-migration-archive +func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + s.client.clientMu.Lock() + defer s.client.clientMu.Unlock() + + // Disable the redirect mechanism because AWS fails if the GitHub auth token is provided. + var loc string + saveRedirect := s.client.client.CheckRedirect + s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + loc = req.URL.String() + return errors.New("disable redirect") + } + defer func() { s.client.client.CheckRedirect = saveRedirect }() + + _, err = s.client.Do(ctx, req, nil) // expect error from disable redirect + if err == nil { + return "", errors.New("expected redirect, none provided") + } + if !strings.Contains(err.Error(), "disable redirect") { + return "", err + } + return loc, nil +} + +// DeleteMigration deletes a previous migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/orgs#delete-an-organization-migration-archive +func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnlockRepo unlocks a repository that was locked for migration. +// id is the migration ID. +// You should unlock each migrated repository and delete them when the migration +// is complete and you no longer need the source data. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/orgs#unlock-an-organization-repository +func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/migrations_source_import.go b/vendor/github.com/google/go-github/v45/github/migrations_source_import.go new file mode 100644 index 0000000000..74a04b22a4 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/migrations_source_import.go @@ -0,0 +1,305 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Import represents a repository import request. +type Import struct { + // The URL of the originating repository. + VCSURL *string `json:"vcs_url,omitempty"` + // The originating VCS type. Can be one of 'subversion', 'git', + // 'mercurial', or 'tfvc'. Without this parameter, the import job will + // take additional time to detect the VCS type before beginning the + // import. This detection step will be reflected in the response. + VCS *string `json:"vcs,omitempty"` + // VCSUsername and VCSPassword are only used for StartImport calls that + // are importing a password-protected repository. + VCSUsername *string `json:"vcs_username,omitempty"` + VCSPassword *string `json:"vcs_password,omitempty"` + // For a tfvc import, the name of the project that is being imported. + TFVCProject *string `json:"tfvc_project,omitempty"` + + // LFS related fields that may be preset in the Import Progress response + + // Describes whether the import has been opted in or out of using Git + // LFS. The value can be 'opt_in', 'opt_out', or 'undecided' if no + // action has been taken. + UseLFS *string `json:"use_lfs,omitempty"` + // Describes whether files larger than 100MB were found during the + // importing step. + HasLargeFiles *bool `json:"has_large_files,omitempty"` + // The total size in gigabytes of files larger than 100MB found in the + // originating repository. + LargeFilesSize *int `json:"large_files_size,omitempty"` + // The total number of files larger than 100MB found in the originating + // repository. To see a list of these files, call LargeFiles. + LargeFilesCount *int `json:"large_files_count,omitempty"` + + // Identifies the current status of an import. An import that does not + // have errors will progress through these steps: + // + // detecting - the "detection" step of the import is in progress + // because the request did not include a VCS parameter. The + // import is identifying the type of source control present at + // the URL. + // importing - the "raw" step of the import is in progress. This is + // where commit data is fetched from the original repository. + // The import progress response will include CommitCount (the + // total number of raw commits that will be imported) and + // Percent (0 - 100, the current progress through the import). + // mapping - the "rewrite" step of the import is in progress. This + // is where SVN branches are converted to Git branches, and + // where author updates are applied. The import progress + // response does not include progress information. + // pushing - the "push" step of the import is in progress. This is + // where the importer updates the repository on GitHub. The + // import progress response will include PushPercent, which is + // the percent value reported by git push when it is "Writing + // objects". + // complete - the import is complete, and the repository is ready + // on GitHub. + // + // If there are problems, you will see one of these in the status field: + // + // auth_failed - the import requires authentication in order to + // connect to the original repository. Make an UpdateImport + // request, and include VCSUsername and VCSPassword. + // error - the import encountered an error. The import progress + // response will include the FailedStep and an error message. + // Contact GitHub support for more information. + // detection_needs_auth - the importer requires authentication for + // the originating repository to continue detection. Make an + // UpdatImport request, and include VCSUsername and + // VCSPassword. + // detection_found_nothing - the importer didn't recognize any + // source control at the URL. + // detection_found_multiple - the importer found several projects + // or repositories at the provided URL. When this is the case, + // the Import Progress response will also include a + // ProjectChoices field with the possible project choices as + // values. Make an UpdateImport request, and include VCS and + // (if applicable) TFVCProject. + Status *string `json:"status,omitempty"` + CommitCount *int `json:"commit_count,omitempty"` + StatusText *string `json:"status_text,omitempty"` + AuthorsCount *int `json:"authors_count,omitempty"` + Percent *int `json:"percent,omitempty"` + PushPercent *int `json:"push_percent,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + AuthorsURL *string `json:"authors_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + Message *string `json:"message,omitempty"` + FailedStep *string `json:"failed_step,omitempty"` + + // Human readable display name, provided when the Import appears as + // part of ProjectChoices. + HumanName *string `json:"human_name,omitempty"` + + // When the importer finds several projects or repositories at the + // provided URLs, this will identify the available choices. Call + // UpdateImport with the selected Import value. + ProjectChoices []*Import `json:"project_choices,omitempty"` +} + +func (i Import) String() string { + return Stringify(i) +} + +// SourceImportAuthor identifies an author imported from a source repository. +// +// GitHub API docs: https://docs.github.com/en/rest/migration/source_imports/#get-commit-authors +type SourceImportAuthor struct { + ID *int64 `json:"id,omitempty"` + RemoteID *string `json:"remote_id,omitempty"` + RemoteName *string `json:"remote_name,omitempty"` + Email *string `json:"email,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + ImportURL *string `json:"import_url,omitempty"` +} + +func (a SourceImportAuthor) String() string { + return Stringify(a) +} + +// LargeFile identifies a file larger than 100MB found during a repository import. +// +// GitHub API docs: https://docs.github.com/en/rest/migration/source_imports/#get-large-files +type LargeFile struct { + RefName *string `json:"ref_name,omitempty"` + Path *string `json:"path,omitempty"` + OID *string `json:"oid,omitempty"` + Size *int `json:"size,omitempty"` +} + +func (f LargeFile) String() string { + return Stringify(f) +} + +// StartImport initiates a repository import. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/source-imports#start-an-import +func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("PUT", u, in) + if err != nil { + return nil, nil, err + } + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// ImportProgress queries for the status and progress of an ongoing repository import. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/source-imports#get-an-import-status +func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// UpdateImport initiates a repository import. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/source-imports#update-an-import +func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("PATCH", u, in) + if err != nil { + return nil, nil, err + } + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// CommitAuthors gets the authors mapped from the original repository. +// +// Each type of source control system represents authors in a different way. +// For example, a Git commit author has a display name and an email address, +// but a Subversion commit author just has a username. The GitHub Importer will +// make the author information valid, but the author might not be correct. For +// example, it will change the bare Subversion username "hubot" into something +// like "hubot ". +// +// This method and MapCommitAuthor allow you to provide correct Git author +// information. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/source-imports#get-commit-authors +func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string) ([]*SourceImportAuthor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var authors []*SourceImportAuthor + resp, err := s.client.Do(ctx, req, &authors) + if err != nil { + return nil, resp, err + } + + return authors, resp, nil +} + +// MapCommitAuthor updates an author's identity for the import. Your +// application can continue updating authors any time before you push new +// commits to the repository. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/source-imports#map-a-commit-author +func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo string, id int64, author *SourceImportAuthor) (*SourceImportAuthor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, author) + if err != nil { + return nil, nil, err + } + + out := new(SourceImportAuthor) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// SetLFSPreference sets whether imported repositories should use Git LFS for +// files larger than 100MB. Only the UseLFS field on the provided Import is +// used. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/source-imports#update-git-lfs-preference +func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/lfs", owner, repo) + req, err := s.client.NewRequest("PATCH", u, in) + if err != nil { + return nil, nil, err + } + + out := new(Import) + resp, err := s.client.Do(ctx, req, out) + if err != nil { + return nil, resp, err + } + + return out, resp, nil +} + +// LargeFiles lists files larger than 100MB found during the import. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/source-imports#get-large-files +func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ([]*LargeFile, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var files []*LargeFile + resp, err := s.client.Do(ctx, req, &files) + if err != nil { + return nil, resp, err + } + + return files, resp, nil +} + +// CancelImport stops an import for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/source-imports#cancel-an-import +func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/import", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/migrations_user.go b/vendor/github.com/google/go-github/v45/github/migrations_user.go new file mode 100644 index 0000000000..b8a0d608d6 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/migrations_user.go @@ -0,0 +1,214 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "net/http" +) + +// UserMigration represents a GitHub migration (archival). +type UserMigration struct { + ID *int64 `json:"id,omitempty"` + GUID *string `json:"guid,omitempty"` + // State is the current state of a migration. + // Possible values are: + // "pending" which means the migration hasn't started yet, + // "exporting" which means the migration is in progress, + // "exported" which means the migration finished successfully, or + // "failed" which means the migration failed. + State *string `json:"state,omitempty"` + // LockRepositories indicates whether repositories are locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` + URL *string `json:"url,omitempty"` + CreatedAt *string `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + Repositories []*Repository `json:"repositories,omitempty"` +} + +func (m UserMigration) String() string { + return Stringify(m) +} + +// UserMigrationOptions specifies the optional parameters to Migration methods. +type UserMigrationOptions struct { + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories bool + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments bool +} + +// startUserMigration represents the body of a StartMigration request. +type startUserMigration struct { + // Repositories is a slice of repository names to migrate. + Repositories []string `json:"repositories,omitempty"` + + // LockRepositories indicates whether repositories should be locked (to prevent + // manipulation) while migrating data. + LockRepositories *bool `json:"lock_repositories,omitempty"` + + // ExcludeAttachments indicates whether attachments should be excluded from + // the migration (to reduce migration archive file size). + ExcludeAttachments *bool `json:"exclude_attachments,omitempty"` +} + +// StartUserMigration starts the generation of a migration archive. +// repos is a slice of repository names to migrate. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/users#start-a-user-migration +func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opts *UserMigrationOptions) (*UserMigration, *Response, error) { + u := "user/migrations" + + body := &startUserMigration{Repositories: repos} + if opts != nil { + body.LockRepositories = Bool(opts.LockRepositories) + body.ExcludeAttachments = Bool(opts.ExcludeAttachments) + } + + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &UserMigration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// ListUserMigrations lists the most recent migrations. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/users#list-user-migrations +func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigration, *Response, error) { + u := "user/migrations" + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + var m []*UserMigration + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// UserMigrationStatus gets the status of a specific migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/users#get-a-user-migration-status +func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (*UserMigration, *Response, error) { + u := fmt.Sprintf("user/migrations/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &UserMigration{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// UserMigrationArchiveURL gets the URL for a specific migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/users#download-a-user-migration-archive +func (s *MigrationService) UserMigrationArchiveURL(ctx context.Context, id int64) (string, error) { + url := fmt.Sprintf("user/migrations/%v/archive", id) + + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return "", err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + m := &UserMigration{} + + var loc string + originalRedirect := s.client.client.CheckRedirect + s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + loc = req.URL.String() + return http.ErrUseLastResponse + } + defer func() { + s.client.client.CheckRedirect = originalRedirect + }() + resp, err := s.client.Do(ctx, req, m) + if err == nil { + return "", errors.New("expected redirect, none provided") + } + loc = resp.Header.Get("Location") + return loc, nil +} + +// DeleteUserMigration will delete a previous migration archive. +// id is the migration ID. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/users#delete-a-user-migration-archive +func (s *MigrationService) DeleteUserMigration(ctx context.Context, id int64) (*Response, error) { + url := fmt.Sprintf("user/migrations/%v/archive", id) + + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnlockUserRepo will unlock a repo that was locked for migration. +// id is migration ID. +// You should unlock each migrated repository and delete them when the migration +// is complete and you no longer need the source data. +// +// GitHub API docs: https://docs.github.com/en/rest/migrations/users#unlock-a-user-repository +func (s *MigrationService) UnlockUserRepo(ctx context.Context, id int64, repo string) (*Response, error) { + url := fmt.Sprintf("user/migrations/%v/repos/%v/lock", id, repo) + + req, err := s.client.NewRequest("DELETE", url, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMigrationsPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/misc.go b/vendor/github.com/google/go-github/v45/github/misc.go new file mode 100644 index 0000000000..412d1e2b95 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/misc.go @@ -0,0 +1,271 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "net/url" +) + +// MarkdownOptions specifies optional parameters to the Markdown method. +type MarkdownOptions struct { + // Mode identifies the rendering mode. Possible values are: + // markdown - render a document as plain Markdown, just like + // README files are rendered. + // + // gfm - to render a document as user-content, e.g. like user + // comments or issues are rendered. In GFM mode, hard line breaks are + // always taken into account, and issue and user mentions are linked + // accordingly. + // + // Default is "markdown". + Mode string + + // Context identifies the repository context. Only taken into account + // when rendering as "gfm". + Context string +} + +type markdownRequest struct { + Text *string `json:"text,omitempty"` + Mode *string `json:"mode,omitempty"` + Context *string `json:"context,omitempty"` +} + +// Markdown renders an arbitrary Markdown document. +// +// GitHub API docs: https://docs.github.com/en/rest/markdown/ +func (c *Client) Markdown(ctx context.Context, text string, opts *MarkdownOptions) (string, *Response, error) { + request := &markdownRequest{Text: String(text)} + if opts != nil { + if opts.Mode != "" { + request.Mode = String(opts.Mode) + } + if opts.Context != "" { + request.Context = String(opts.Context) + } + } + + req, err := c.NewRequest("POST", "markdown", request) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := c.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// ListEmojis returns the emojis available to use on GitHub. +// +// GitHub API docs: https://docs.github.com/en/rest/emojis/ +func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error) { + req, err := c.NewRequest("GET", "emojis", nil) + if err != nil { + return nil, nil, err + } + + var emoji map[string]string + resp, err := c.Do(ctx, req, &emoji) + if err != nil { + return nil, resp, err + } + + return emoji, resp, nil +} + +// CodeOfConduct represents a code of conduct. +type CodeOfConduct struct { + Name *string `json:"name,omitempty"` + Key *string `json:"key,omitempty"` + URL *string `json:"url,omitempty"` + Body *string `json:"body,omitempty"` +} + +func (c *CodeOfConduct) String() string { + return Stringify(c) +} + +// ListCodesOfConduct returns all codes of conduct. +// +// GitHub API docs: https://docs.github.com/en/rest/codes_of_conduct/#list-all-codes-of-conduct +func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error) { + req, err := c.NewRequest("GET", "codes_of_conduct", nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + var cs []*CodeOfConduct + resp, err := c.Do(ctx, req, &cs) + if err != nil { + return nil, resp, err + } + + return cs, resp, nil +} + +// GetCodeOfConduct returns an individual code of conduct. +// +// https://docs.github.com/en/rest/codes_of_conduct/#get-an-individual-code-of-conduct +func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error) { + u := fmt.Sprintf("codes_of_conduct/%s", key) + req, err := c.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + coc := new(CodeOfConduct) + resp, err := c.Do(ctx, req, coc) + if err != nil { + return nil, resp, err + } + + return coc, resp, nil +} + +// APIMeta represents metadata about the GitHub API. +type APIMeta struct { + // An Array of IP addresses in CIDR format specifying the addresses + // that incoming service hooks will originate from on GitHub.com. + Hooks []string `json:"hooks,omitempty"` + + // An Array of IP addresses in CIDR format specifying the Git servers + // for GitHub.com. + Git []string `json:"git,omitempty"` + + // Whether authentication with username and password is supported. + // (GitHub Enterprise instances using CAS or OAuth for authentication + // will return false. Features like Basic Authentication with a + // username and password, sudo mode, and two-factor authentication are + // not supported on these servers.) + VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"` + + // An array of IP addresses in CIDR format specifying the addresses + // which serve GitHub Pages websites. + Pages []string `json:"pages,omitempty"` + + // An Array of IP addresses specifying the addresses that source imports + // will originate from on GitHub.com. + Importer []string `json:"importer,omitempty"` + + // An array of IP addresses in CIDR format specifying the IP addresses + // GitHub Actions will originate from. + Actions []string `json:"actions,omitempty"` + + // An array of IP addresses in CIDR format specifying the IP addresses + // Dependabot will originate from. + Dependabot []string `json:"dependabot,omitempty"` + + // A map of algorithms to SSH key fingerprints. + SSHKeyFingerprints map[string]string `json:"ssh_key_fingerprints,omitempty"` + + // An array of SSH keys. + SSHKeys []string `json:"ssh_keys,omitempty"` +} + +// APIMeta returns information about GitHub.com, the service. Or, if you access +// this endpoint on your organization’s GitHub Enterprise installation, this +// endpoint provides information about that installation. +// +// GitHub API docs: https://docs.github.com/en/rest/meta#get-github-meta-information +func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error) { + req, err := c.NewRequest("GET", "meta", nil) + if err != nil { + return nil, nil, err + } + + meta := new(APIMeta) + resp, err := c.Do(ctx, req, meta) + if err != nil { + return nil, resp, err + } + + return meta, resp, nil +} + +// Octocat returns an ASCII art octocat with the specified message in a speech +// bubble. If message is empty, a random zen phrase is used. +func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error) { + u := "octocat" + if message != "" { + u = fmt.Sprintf("%s?s=%s", u, url.QueryEscape(message)) + } + + req, err := c.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := c.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// Zen returns a random line from The Zen of GitHub. +// +// see also: http://warpspire.com/posts/taste/ +func (c *Client) Zen(ctx context.Context) (string, *Response, error) { + req, err := c.NewRequest("GET", "zen", nil) + if err != nil { + return "", nil, err + } + + buf := new(bytes.Buffer) + resp, err := c.Do(ctx, req, buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// ServiceHook represents a hook that has configuration settings, a list of +// available events, and default events. +type ServiceHook struct { + Name *string `json:"name,omitempty"` + Events []string `json:"events,omitempty"` + SupportedEvents []string `json:"supported_events,omitempty"` + Schema [][]string `json:"schema,omitempty"` +} + +func (s *ServiceHook) String() string { + return Stringify(s) +} + +// ListServiceHooks lists all of the available service hooks. +// +// GitHub API docs: https://developer.github.com/webhooks/#services +func (c *Client) ListServiceHooks(ctx context.Context) ([]*ServiceHook, *Response, error) { + u := "hooks" + req, err := c.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*ServiceHook + resp, err := c.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs.go b/vendor/github.com/google/go-github/v45/github/orgs.go new file mode 100644 index 0000000000..80979db350 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs.go @@ -0,0 +1,272 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// OrganizationsService provides access to the organization related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/ +type OrganizationsService service + +// Organization represents a GitHub organization account. +type Organization struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Name *string `json:"name,omitempty"` + Company *string `json:"company,omitempty"` + Blog *string `json:"blog,omitempty"` + Location *string `json:"location,omitempty"` + Email *string `json:"email,omitempty"` + TwitterUsername *string `json:"twitter_username,omitempty"` + Description *string `json:"description,omitempty"` + PublicRepos *int `json:"public_repos,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` + Followers *int `json:"followers,omitempty"` + Following *int `json:"following,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + TotalPrivateRepos *int `json:"total_private_repos,omitempty"` + OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + DiskUsage *int `json:"disk_usage,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + BillingEmail *string `json:"billing_email,omitempty"` + Type *string `json:"type,omitempty"` + Plan *Plan `json:"plan,omitempty"` + TwoFactorRequirementEnabled *bool `json:"two_factor_requirement_enabled,omitempty"` + IsVerified *bool `json:"is_verified,omitempty"` + HasOrganizationProjects *bool `json:"has_organization_projects,omitempty"` + HasRepositoryProjects *bool `json:"has_repository_projects,omitempty"` + + // DefaultRepoPermission can be one of: "read", "write", "admin", or "none". (Default: "read"). + // It is only used in OrganizationsService.Edit. + DefaultRepoPermission *string `json:"default_repository_permission,omitempty"` + // DefaultRepoSettings can be one of: "read", "write", "admin", or "none". (Default: "read"). + // It is only used in OrganizationsService.Get. + DefaultRepoSettings *string `json:"default_repository_settings,omitempty"` + + // MembersCanCreateRepos default value is true and is only used in Organizations.Edit. + MembersCanCreateRepos *bool `json:"members_can_create_repositories,omitempty"` + + // https://developer.github.com/changes/2019-12-03-internal-visibility-changes/#rest-v3-api + MembersCanCreatePublicRepos *bool `json:"members_can_create_public_repositories,omitempty"` + MembersCanCreatePrivateRepos *bool `json:"members_can_create_private_repositories,omitempty"` + MembersCanCreateInternalRepos *bool `json:"members_can_create_internal_repositories,omitempty"` + + // MembersAllowedRepositoryCreationType denotes if organization members can create repositories + // and the type of repositories they can create. Possible values are: "all", "private", or "none". + // + // Deprecated: Use MembersCanCreatePublicRepos, MembersCanCreatePrivateRepos, MembersCanCreateInternalRepos + // instead. The new fields overrides the existing MembersAllowedRepositoryCreationType during 'edit' + // operation and does not consider 'internal' repositories during 'get' operation + MembersAllowedRepositoryCreationType *string `json:"members_allowed_repository_creation_type,omitempty"` + + // MembersCanCreatePages toggles whether organization members can create GitHub Pages sites. + MembersCanCreatePages *bool `json:"members_can_create_pages,omitempty"` + // MembersCanCreatePublicPages toggles whether organization members can create public GitHub Pages sites. + MembersCanCreatePublicPages *bool `json:"members_can_create_public_pages,omitempty"` + // MembersCanCreatePrivatePages toggles whether organization members can create private GitHub Pages sites. + MembersCanCreatePrivatePages *bool `json:"members_can_create_private_pages,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + HooksURL *string `json:"hooks_url,omitempty"` + IssuesURL *string `json:"issues_url,omitempty"` + MembersURL *string `json:"members_url,omitempty"` + PublicMembersURL *string `json:"public_members_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` +} + +// OrganizationInstallations represents GitHub app installations for an organization. +type OrganizationInstallations struct { + TotalCount *int `json:"total_count,omitempty"` + Installations []*Installation `json:"installations,omitempty"` +} + +func (o Organization) String() string { + return Stringify(o) +} + +// Plan represents the payment plan for an account. See plans at https://github.com/plans. +type Plan struct { + Name *string `json:"name,omitempty"` + Space *int `json:"space,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + PrivateRepos *int `json:"private_repos,omitempty"` + FilledSeats *int `json:"filled_seats,omitempty"` + Seats *int `json:"seats,omitempty"` +} + +func (p Plan) String() string { + return Stringify(p) +} + +// OrganizationsListOptions specifies the optional parameters to the +// OrganizationsService.ListAll method. +type OrganizationsListOptions struct { + // Since filters Organizations by ID. + Since int64 `url:"since,omitempty"` + + // Note: Pagination is powered exclusively by the Since parameter, + // ListOptions.Page has no effect. + // ListOptions.PerPage controls an undocumented GitHub API parameter. + ListOptions +} + +// ListAll lists all organizations, in the order that they were created on GitHub. +// +// Note: Pagination is powered exclusively by the since parameter. To continue +// listing the next set of organizations, use the ID of the last-returned organization +// as the opts.Since parameter for the next call. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/orgs#list-organizations +func (s *OrganizationsService) ListAll(ctx context.Context, opts *OrganizationsListOptions) ([]*Organization, *Response, error) { + u, err := addOptions("organizations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + orgs := []*Organization{} + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + return orgs, resp, nil +} + +// List the organizations for a user. Passing the empty string will list +// organizations for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/orgs#list-organizations-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/orgs/orgs#list-organizations-for-a-user +func (s *OrganizationsService) List(ctx context.Context, user string, opts *ListOptions) ([]*Organization, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/orgs", user) + } else { + u = "user/orgs" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var orgs []*Organization + resp, err := s.client.Do(ctx, req, &orgs) + if err != nil { + return nil, resp, err + } + + return orgs, resp, nil +} + +// Get fetches an organization by name. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/orgs#get-an-organization +func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organization, *Response, error) { + u := fmt.Sprintf("orgs/%v", org) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview) + + organization := new(Organization) + resp, err := s.client.Do(ctx, req, organization) + if err != nil { + return nil, resp, err + } + + return organization, resp, nil +} + +// GetByID fetches an organization. +// +// Note: GetByID uses the undocumented GitHub API endpoint /organizations/:id. +func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organization, *Response, error) { + u := fmt.Sprintf("organizations/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + organization := new(Organization) + resp, err := s.client.Do(ctx, req, organization) + if err != nil { + return nil, resp, err + } + + return organization, resp, nil +} + +// Edit an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/orgs#update-an-organization +func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) { + u := fmt.Sprintf("orgs/%v", name) + req, err := s.client.NewRequest("PATCH", u, org) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview) + + o := new(Organization) + resp, err := s.client.Do(ctx, req, o) + if err != nil { + return nil, resp, err + } + + return o, resp, nil +} + +// ListInstallations lists installations for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/orgs#list-app-installations-for-an-organization +func (s *OrganizationsService) ListInstallations(ctx context.Context, org string, opts *ListOptions) (*OrganizationInstallations, *Response, error) { + u := fmt.Sprintf("orgs/%v/installations", org) + + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + result := new(OrganizationInstallations) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_actions_allowed.go b/vendor/github.com/google/go-github/v45/github/orgs_actions_allowed.go new file mode 100644 index 0000000000..e3b35b1df1 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_actions_allowed.go @@ -0,0 +1,63 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsAllowed represents selected actions that are allowed. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions +type ActionsAllowed struct { + GithubOwnedAllowed *bool `json:"github_owned_allowed,omitempty"` + VerifiedAllowed *bool `json:"verified_allowed,omitempty"` + PatternsAllowed []string `json:"patterns_allowed,omitempty"` +} + +func (a ActionsAllowed) String() string { + return Stringify(a) +} + +// GetActionsAllowed gets the actions that are allowed in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-an-organization +func (s *OrganizationsService) GetActionsAllowed(ctx context.Context, org string) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/selected-actions", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsAllowed := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, actionsAllowed) + if err != nil { + return nil, resp, err + } + + return actionsAllowed, resp, nil +} + +// EditActionsAllowed sets the actions that are allowed in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-an-organization +func (s *OrganizationsService) EditActionsAllowed(ctx context.Context, org string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions/selected-actions", org) + req, err := s.client.NewRequest("PUT", u, actionsAllowed) + if err != nil { + return nil, nil, err + } + + p := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_actions_permissions.go b/vendor/github.com/google/go-github/v45/github/orgs_actions_permissions.go new file mode 100644 index 0000000000..6d1db2ee0a --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_actions_permissions.go @@ -0,0 +1,63 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsPermissions represents a policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions +type ActionsPermissions struct { + EnabledRepositories *string `json:"enabled_repositories,omitempty"` + AllowedActions *string `json:"allowed_actions,omitempty"` + SelectedActionsURL *string `json:"selected_actions_url,omitempty"` +} + +func (a ActionsPermissions) String() string { + return Stringify(a) +} + +// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#get-github-actions-permissions-for-an-organization +func (s *OrganizationsService) GetActionsPermissions(ctx context.Context, org string) (*ActionsPermissions, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissions) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditActionsPermissions sets the permissions policy for repositories and allowed actions in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#set-github-actions-permissions-for-an-organization +func (s *OrganizationsService) EditActionsPermissions(ctx context.Context, org string, actionsPermissions ActionsPermissions) (*ActionsPermissions, *Response, error) { + u := fmt.Sprintf("orgs/%v/actions/permissions", org) + req, err := s.client.NewRequest("PUT", u, actionsPermissions) + if err != nil { + return nil, nil, err + } + + p := new(ActionsPermissions) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_audit_log.go b/vendor/github.com/google/go-github/v45/github/orgs_audit_log.go new file mode 100644 index 0000000000..52bacfed9a --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_audit_log.go @@ -0,0 +1,116 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetAuditLogOptions sets up optional parameters to query audit-log endpoint. +type GetAuditLogOptions struct { + Phrase *string `url:"phrase,omitempty"` // A search phrase. (Optional.) + Include *string `url:"include,omitempty"` // Event type includes. Can be one of "web", "git", "all". Default: "web". (Optional.) + Order *string `url:"order,omitempty"` // The order of audit log events. Can be one of "asc" or "desc". Default: "desc". (Optional.) + + ListCursorOptions +} + +// HookConfig describes metadata about a webhook configuration. +type HookConfig struct { + ContentType *string `json:"content_type,omitempty"` + InsecureSSL *string `json:"insecure_ssl,omitempty"` + URL *string `json:"url,omitempty"` + + // Secret is returned obfuscated by GitHub, but it can be set for outgoing requests. + Secret *string `json:"secret,omitempty"` +} + +// AuditEntry describes the fields that may be represented by various audit-log "action" entries. +// For a list of actions see - https://docs.github.com/en/github/setting-up-and-managing-organizations-and-teams/reviewing-the-audit-log-for-your-organization#audit-log-actions +type AuditEntry struct { + Action *string `json:"action,omitempty"` // The name of the action that was performed, for example `user.login` or `repo.create`. + Active *bool `json:"active,omitempty"` + ActiveWas *bool `json:"active_was,omitempty"` + Actor *string `json:"actor,omitempty"` // The actor who performed the action. + BlockedUser *string `json:"blocked_user,omitempty"` + Business *string `json:"business,omitempty"` + CancelledAt *Timestamp `json:"cancelled_at,omitempty"` + CompletedAt *Timestamp `json:"completed_at,omitempty"` + Conclusion *string `json:"conclusion,omitempty"` + Config *HookConfig `json:"config,omitempty"` + ConfigWas *HookConfig `json:"config_was,omitempty"` + ContentType *string `json:"content_type,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + DeployKeyFingerprint *string `json:"deploy_key_fingerprint,omitempty"` + DocumentID *string `json:"_document_id,omitempty"` + Emoji *string `json:"emoji,omitempty"` + EnvironmentName *string `json:"environment_name,omitempty"` + Event *string `json:"event,omitempty"` + Events []string `json:"events,omitempty"` + EventsWere []string `json:"events_were,omitempty"` + Explanation *string `json:"explanation,omitempty"` + Fingerprint *string `json:"fingerprint,omitempty"` + HeadBranch *string `json:"head_branch,omitempty"` + HeadSHA *string `json:"head_sha,omitempty"` + HookID *int64 `json:"hook_id,omitempty"` + IsHostedRunner *bool `json:"is_hosted_runner,omitempty"` + JobName *string `json:"job_name,omitempty"` + LimitedAvailability *bool `json:"limited_availability,omitempty"` + Message *string `json:"message,omitempty"` + Name *string `json:"name,omitempty"` + OldUser *string `json:"old_user,omitempty"` + OpenSSHPublicKey *string `json:"openssh_public_key,omitempty"` + Org *string `json:"org,omitempty"` + PreviousVisibility *string `json:"previous_visibility,omitempty"` + ReadOnly *string `json:"read_only,omitempty"` + Repo *string `json:"repo,omitempty"` + Repository *string `json:"repository,omitempty"` + RepositoryPublic *bool `json:"repository_public,omitempty"` + RunnerGroupID *int64 `json:"runner_group_id,omitempty"` + RunnerGroupName *string `json:"runner_group_name,omitempty"` + RunnerID *int64 `json:"runner_id,omitempty"` + RunnerLabels []string `json:"runner_labels,omitempty"` + RunnerName *string `json:"runner_name,omitempty"` + SecretsPassed []string `json:"secrets_passed,omitempty"` + SourceVersion *string `json:"source_version,omitempty"` + StartedAt *Timestamp `json:"started_at,omitempty"` + TargetLogin *string `json:"target_login,omitempty"` + TargetVersion *string `json:"target_version,omitempty"` + Team *string `json:"team,omitempty"` + Timestamp *Timestamp `json:"@timestamp,omitempty"` // The time the audit log event occurred, given as a [Unix timestamp](http://en.wikipedia.org/wiki/Unix_time). + TransportProtocolName *string `json:"transport_protocol_name,omitempty"` // A human readable name for the protocol (for example, HTTP or SSH) used to transfer Git data. + TransportProtocol *int `json:"transport_protocol,omitempty"` // The type of protocol (for example, HTTP=1 or SSH=2) used to transfer Git data. + TriggerID *int64 `json:"trigger_id,omitempty"` + User *string `json:"user,omitempty"` // The user that was affected by the action performed (if available). + Visibility *string `json:"visibility,omitempty"` // The repository visibility, for example `public` or `private`. + WorkflowID *int64 `json:"workflow_id,omitempty"` + WorkflowRunID *int64 `json:"workflow_run_id,omitempty"` +} + +// GetAuditLog gets the audit-log entries for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/orgs#get-the-audit-log-for-an-organization +func (s *OrganizationsService) GetAuditLog(ctx context.Context, org string, opts *GetAuditLogOptions) ([]*AuditEntry, *Response, error) { + u := fmt.Sprintf("orgs/%v/audit-log", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var auditEntries []*AuditEntry + resp, err := s.client.Do(ctx, req, &auditEntries) + if err != nil { + return nil, resp, err + } + + return auditEntries, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_custom_roles.go b/vendor/github.com/google/go-github/v45/github/orgs_custom_roles.go new file mode 100644 index 0000000000..9904685b94 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_custom_roles.go @@ -0,0 +1,46 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// OrganizationCustomRepoRoles represents custom repository roles available in specified organization. +type OrganizationCustomRepoRoles struct { + TotalCount *int `json:"total_count,omitempty"` + CustomRepoRoles []*CustomRepoRoles `json:"custom_roles,omitempty"` +} + +// CustomRepoRoles represents custom repository roles for an organization. +// See https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/managing-custom-repository-roles-for-an-organization +// for more information. +type CustomRepoRoles struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` +} + +// ListCustomRepoRoles lists the custom repository roles available in this organization. +// In order to see custom repository roles in an organization, the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/custom-roles#list-custom-repository-roles-in-an-organization +func (s *OrganizationsService) ListCustomRepoRoles(ctx context.Context, org string) (*OrganizationCustomRepoRoles, *Response, error) { + u := fmt.Sprintf("orgs/%v/custom_roles", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + customRepoRoles := new(OrganizationCustomRepoRoles) + resp, err := s.client.Do(ctx, req, customRepoRoles) + if err != nil { + return nil, resp, err + } + + return customRepoRoles, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_hooks.go b/vendor/github.com/google/go-github/v45/github/orgs_hooks.go new file mode 100644 index 0000000000..c0dd51e24e --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_hooks.go @@ -0,0 +1,130 @@ +// Copyright 2015 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHooks lists all Hooks for the specified organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#list-organization-webhooks +func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opts *ListOptions) ([]*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*Hook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#get-an-organization-webhook +func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hook := new(Hook) + resp, err := s.client.Do(ctx, req, hook) + if err != nil { + return nil, resp, err + } + + return hook, resp, nil +} + +// CreateHook creates a Hook for the specified org. +// Config is a required field. +// +// Note that only a subset of the hook fields are used and hook must +// not be nil. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#create-an-organization-webhook +func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks", org) + + hookReq := &createHookRequest{ + Name: "web", + Events: hook.Events, + Active: hook.Active, + Config: hook.Config, + } + + req, err := s.client.NewRequest("POST", u, hookReq) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#update-an-organization-webhook +func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#ping-an-organization-webhook +func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#delete-an-organization-webhook +func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%d", org, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_hooks_deliveries.go b/vendor/github.com/google/go-github/v45/github/orgs_hooks_deliveries.go new file mode 100644 index 0000000000..1bfad409ea --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_hooks_deliveries.go @@ -0,0 +1,73 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListHookDeliveries lists webhook deliveries for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#list-deliveries-for-an-organization-webhook +func (s *OrganizationsService) ListHookDeliveries(ctx context.Context, org string, id int64, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries", org, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns a delivery for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#get-a-webhook-delivery-for-an-organization-webhook +func (s *OrganizationsService) GetHookDelivery(ctx context.Context, owner string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries/%v", owner, hookID, deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for a webhook configured in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/webhooks#redeliver-a-delivery-for-an-organization-webhook +func (s *OrganizationsService) RedeliverHookDelivery(ctx context.Context, owner string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("orgs/%v/hooks/%v/deliveries/%v/attempts", owner, hookID, deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_members.go b/vendor/github.com/google/go-github/v45/github/orgs_members.go new file mode 100644 index 0000000000..38f43bad5a --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_members.go @@ -0,0 +1,391 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Membership represents the status of a user's membership in an organization or team. +type Membership struct { + URL *string `json:"url,omitempty"` + + // State is the user's status within the organization or team. + // Possible values are: "active", "pending" + State *string `json:"state,omitempty"` + + // Role identifies the user's role within the organization or team. + // Possible values for organization membership: + // member - non-owner organization member + // admin - organization owner + // + // Possible values for team membership are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description + Role *string `json:"role,omitempty"` + + // For organization membership, the API URL of the organization. + OrganizationURL *string `json:"organization_url,omitempty"` + + // For organization membership, the organization the membership is for. + Organization *Organization `json:"organization,omitempty"` + + // For organization membership, the user the membership is for. + User *User `json:"user,omitempty"` +} + +func (m Membership) String() string { + return Stringify(m) +} + +// ListMembersOptions specifies optional parameters to the +// OrganizationsService.ListMembers method. +type ListMembersOptions struct { + // If true (or if the authenticated user is not an owner of the + // organization), list only publicly visible members. + PublicOnly bool `url:"-"` + + // Filter members returned in the list. Possible values are: + // 2fa_disabled, all. Default is "all". + Filter string `url:"filter,omitempty"` + + // Role filters members returned by their role in the organization. + // Possible values are: + // all - all members of the organization, regardless of role + // admin - organization owners + // member - non-owner organization members + // + // Default is "all". + Role string `url:"role,omitempty"` + + ListOptions +} + +// ListMembers lists the members for an organization. If the authenticated +// user is an owner of the organization, this will return both concealed and +// public members, otherwise it will only return public members. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#list-organization-members +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#list-public-organization-members +func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *ListMembersOptions) ([]*User, *Response, error) { + var u string + if opts != nil && opts.PublicOnly { + u = fmt.Sprintf("orgs/%v/public_members", org) + } else { + u = fmt.Sprintf("orgs/%v/members", org) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// IsMember checks if a user is a member of an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#check-organization-membership-for-a-user +func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/members/%v", org, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + member, err := parseBoolResponse(err) + return member, resp, err +} + +// IsPublicMember checks if a user is a public member of an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#check-public-organization-membership-for-a-user +func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + member, err := parseBoolResponse(err) + return member, resp, err +} + +// RemoveMember removes a user from all teams of an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#remove-an-organization-member +func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/members/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// PublicizeMembership publicizes a user's membership in an organization. (A +// user cannot publicize the membership for another user.) +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#set-public-organization-membership-for-the-authenticated-user +func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ConcealMembership conceals a user's membership in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#remove-public-organization-membership-for-the-authenticated-user +func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/public_members/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListOrgMembershipsOptions specifies optional parameters to the +// OrganizationsService.ListOrgMemberships method. +type ListOrgMembershipsOptions struct { + // Filter memberships to include only those with the specified state. + // Possible values are: "active", "pending". + State string `url:"state,omitempty"` + + ListOptions +} + +// ListOrgMemberships lists the organization memberships for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#list-organization-memberships-for-the-authenticated-user +func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opts *ListOrgMembershipsOptions) ([]*Membership, *Response, error) { + u := "user/memberships/orgs" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var memberships []*Membership + resp, err := s.client.Do(ctx, req, &memberships) + if err != nil { + return nil, resp, err + } + + return memberships, resp, nil +} + +// GetOrgMembership gets the membership for a user in a specified organization. +// Passing an empty string for user will get the membership for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#get-an-organization-membership-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#get-organization-membership-for-a-user +func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) + } else { + u = fmt.Sprintf("user/memberships/orgs/%v", org) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + membership := new(Membership) + resp, err := s.client.Do(ctx, req, membership) + if err != nil { + return nil, resp, err + } + + return membership, resp, nil +} + +// EditOrgMembership edits the membership for user in specified organization. +// Passing an empty string for user will edit the membership for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#update-an-organization-membership-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#set-organization-membership-for-a-user +func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) { + var u, method string + if user != "" { + u = fmt.Sprintf("orgs/%v/memberships/%v", org, user) + method = "PUT" + } else { + u = fmt.Sprintf("user/memberships/orgs/%v", org) + method = "PATCH" + } + + req, err := s.client.NewRequest(method, u, membership) + if err != nil { + return nil, nil, err + } + + m := new(Membership) + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// RemoveOrgMembership removes user from the specified organization. If the +// user has been invited to the organization, this will cancel their invitation. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#remove-organization-membership-for-a-user +func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, org string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/memberships/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListPendingOrgInvitations returns a list of pending invitations. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#list-pending-organization-invitations +func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} + +// CreateOrgInvitationOptions specifies the parameters to the OrganizationService.Invite +// method. +type CreateOrgInvitationOptions struct { + // GitHub user ID for the person you are inviting. Not required if you provide Email. + InviteeID *int64 `json:"invitee_id,omitempty"` + // Email address of the person you are inviting, which can be an existing GitHub user. + // Not required if you provide InviteeID + Email *string `json:"email,omitempty"` + // Specify role for new member. Can be one of: + // * admin - Organization owners with full administrative rights to the + // organization and complete access to all repositories and teams. + // * direct_member - Non-owner organization members with ability to see + // other members and join teams by invitation. + // * billing_manager - Non-owner organization members with ability to + // manage the billing settings of your organization. + // Default is "direct_member". + Role *string `json:"role"` + TeamID []int64 `json:"team_ids"` +} + +// CreateOrgInvitation invites people to an organization by using their GitHub user ID or their email address. +// In order to create invitations in an organization, +// the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#create-an-organization-invitation +func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opts *CreateOrgInvitationOptions) (*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations", org) + + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + var invitation *Invitation + resp, err := s.client.Do(ctx, req, &invitation) + if err != nil { + return nil, resp, err + } + + return invitation, resp, nil +} + +// ListOrgInvitationTeams lists all teams associated with an invitation. In order to see invitations in an organization, +// the authenticated user must be an organization owner. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#list-organization-invitation-teams +func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var orgInvitationTeams []*Team + resp, err := s.client.Do(ctx, req, &orgInvitationTeams) + if err != nil { + return nil, resp, err + } + + return orgInvitationTeams, resp, nil +} + +// ListFailedOrgInvitations returns a list of failed inviatations. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/members#list-failed-organization-invitations +func (s *OrganizationsService) ListFailedOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/failed_invitations", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var failedInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &failedInvitations) + if err != nil { + return nil, resp, err + } + + return failedInvitations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_outside_collaborators.go b/vendor/github.com/google/go-github/v45/github/orgs_outside_collaborators.go new file mode 100644 index 0000000000..506a494603 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_outside_collaborators.go @@ -0,0 +1,81 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListOutsideCollaboratorsOptions specifies optional parameters to the +// OrganizationsService.ListOutsideCollaborators method. +type ListOutsideCollaboratorsOptions struct { + // Filter outside collaborators returned in the list. Possible values are: + // 2fa_disabled, all. Default is "all". + Filter string `url:"filter,omitempty"` + + ListOptions +} + +// ListOutsideCollaborators lists outside collaborators of organization's repositories. +// This will only work if the authenticated +// user is an owner of the organization. +// +// Warning: The API may change without advance notice during the preview period. +// Preview features are not supported for production use. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/outside-collaborators#list-outside-collaborators-for-an-organization +func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opts *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// RemoveOutsideCollaborator removes a user from the list of outside collaborators; +// consequently, removing them from all the organization's repositories. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/outside-collaborators#remove-outside-collaborator-from-an-organization +func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ConvertMemberToOutsideCollaborator reduces the permission level of a member of the +// organization to that of an outside collaborator. Therefore, they will only +// have access to the repositories that their current team membership allows. +// Responses for converting a non-member or the last owner to an outside collaborator +// are listed in GitHub API docs. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/outside-collaborators#convert-an-organization-member-to-outside-collaborator +func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_packages.go b/vendor/github.com/google/go-github/v45/github/orgs_packages.go new file mode 100644 index 0000000000..9fb11308b8 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_packages.go @@ -0,0 +1,149 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// List the packages for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#list-packages-for-an-organization +func (s *OrganizationsService) ListPackages(ctx context.Context, org string, opts *PackageListOptions) ([]*Package, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var packages []*Package + resp, err := s.client.Do(ctx, req, &packages) + if err != nil { + return nil, resp, err + } + + return packages, resp, nil +} + +// Get a package by name from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#get-a-package-for-an-organization +func (s *OrganizationsService) GetPackage(ctx context.Context, org, packageType, packageName string) (*Package, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, packageName) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pack *Package + resp, err := s.client.Do(ctx, req, &pack) + if err != nil { + return nil, resp, err + } + + return pack, resp, nil +} + +// Delete a package from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#delete-a-package-for-an-organization +func (s *OrganizationsService) DeletePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v", org, packageType, packageName) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Restore a package to an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#restore-a-package-for-an-organization +func (s *OrganizationsService) RestorePackage(ctx context.Context, org, packageType, packageName string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/restore", org, packageType, packageName) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Get all versions of a package in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#get-all-package-versions-for-a-package-owned-by-an-organization +func (s *OrganizationsService) PackageGetAllVersions(ctx context.Context, org, packageType, packageName string, opts *PackageListOptions) ([]*PackageVersion, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions", org, packageType, packageName) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var versions []*PackageVersion + resp, err := s.client.Do(ctx, req, &versions) + if err != nil { + return nil, resp, err + } + + return versions, resp, nil +} + +// Get a specific version of a package in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#get-a-package-version-for-an-organization +func (s *OrganizationsService) PackageGetVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, packageName, packageVersionID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var version *PackageVersion + resp, err := s.client.Do(ctx, req, &version) + if err != nil { + return nil, resp, err + } + + return version, resp, nil +} + +// Delete a package version from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#delete-package-version-for-an-organization +func (s *OrganizationsService) PackageDeleteVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v", org, packageType, packageName, packageVersionID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Restore a package version to an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#restore-package-version-for-an-organization +func (s *OrganizationsService) PackageRestoreVersion(ctx context.Context, org, packageType, packageName string, packageVersionID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/packages/%v/%v/versions/%v/restore", org, packageType, packageName, packageVersionID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_projects.go b/vendor/github.com/google/go-github/v45/github/orgs_projects.go new file mode 100644 index 0000000000..d49eae54dc --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_projects.go @@ -0,0 +1,60 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListProjects lists the projects for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#list-organization-projects +func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opts *ProjectListOptions) ([]*Project, *Response, error) { + u := fmt.Sprintf("orgs/%v/projects", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var projects []*Project + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// CreateProject creates a GitHub Project for the specified organization. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#create-an-organization-project +func (s *OrganizationsService) CreateProject(ctx context.Context, org string, opts *ProjectOptions) (*Project, *Response, error) { + u := fmt.Sprintf("orgs/%v/projects", org) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/orgs_users_blocking.go b/vendor/github.com/google/go-github/v45/github/orgs_users_blocking.go new file mode 100644 index 0000000000..9c6cf60269 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/orgs_users_blocking.go @@ -0,0 +1,91 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListBlockedUsers lists all the users blocked by an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/blocking#list-users-blocked-by-an-organization +func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opts *ListOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/blocks", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + var blockedUsers []*User + resp, err := s.client.Do(ctx, req, &blockedUsers) + if err != nil { + return nil, resp, err + } + + return blockedUsers, resp, nil +} + +// IsBlocked reports whether specified user is blocked from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/blocking#check-if-a-user-is-blocked-by-an-organization +func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + resp, err := s.client.Do(ctx, req, nil) + isBlocked, err := parseBoolResponse(err) + return isBlocked, resp, err +} + +// BlockUser blocks specified user from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/blocking#block-a-user-from-an-organization +func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnblockUser unblocks specified user from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/orgs/blocking#unblock-a-user-from-an-organization +func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/blocks/%v", org, user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/packages.go b/vendor/github.com/google/go-github/v45/github/packages.go new file mode 100644 index 0000000000..ef7df07405 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/packages.go @@ -0,0 +1,143 @@ +// Copyright 2020 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// Package represents a GitHub package. +type Package struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + PackageType *string `json:"package_type,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Owner *User `json:"owner,omitempty"` + PackageVersion *PackageVersion `json:"package_version,omitempty"` + Registry *PackageRegistry `json:"registry,omitempty"` + URL *string `json:"url,omitempty"` + VersionCount *int64 `json:"version_count,omitempty"` + Visibility *string `json:"visibility,omitempty"` + Repository *Repository `json:"repository,omitempty"` +} + +func (p Package) String() string { + return Stringify(p) +} + +// PackageVersion represents a GitHub package version. +type PackageVersion struct { + ID *int64 `json:"id,omitempty"` + Version *string `json:"version,omitempty"` + Summary *string `json:"summary,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + Release *PackageRelease `json:"release,omitempty"` + Manifest *string `json:"manifest,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + TargetOID *string `json:"target_oid,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PackageFiles []*PackageFile `json:"package_files,omitempty"` + Author *User `json:"author,omitempty"` + InstallationCommand *string `json:"installation_command,omitempty"` + Metadata *PackageMetadata `json:"metadata,omitempty"` + PackageHTMLURL *string `json:"package_html_url,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (pv PackageVersion) String() string { + return Stringify(pv) +} + +// PackageRelease represents a GitHub package version release. +type PackageRelease struct { + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ID *int64 `json:"id,omitempty"` + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Draft *bool `json:"draft,omitempty"` + Author *User `json:"author,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` +} + +func (r PackageRelease) String() string { + return Stringify(r) +} + +// PackageFile represents a GitHub package version release file. +type PackageFile struct { + DownloadURL *string `json:"download_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + SHA256 *string `json:"sha256,omitempty"` + SHA1 *string `json:"sha1,omitempty"` + MD5 *string `json:"md5,omitempty"` + ContentType *string `json:"content_type,omitempty"` + State *string `json:"state,omitempty"` + Author *User `json:"author,omitempty"` + Size *int64 `json:"size,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +func (pf PackageFile) String() string { + return Stringify(pf) +} + +// PackageRegistry represents a GitHub package registry. +type PackageRegistry struct { + AboutURL *string `json:"about_url,omitempty"` + Name *string `json:"name,omitempty"` + Type *string `json:"type,omitempty"` + URL *string `json:"url,omitempty"` + Vendor *string `json:"vendor,omitempty"` +} + +func (r PackageRegistry) String() string { + return Stringify(r) +} + +// PackageListOptions represents the optional list options for a package. +type PackageListOptions struct { + // Visibility of packages "public", "internal" or "private". + Visibility *string `url:"visibility,omitempty"` + + // PackageType represents the type of package. + // It can be one of "npm", "maven", "rubygems", "nuget", "docker", or "container". + PackageType *string `url:"package_type,omitempty"` + + // State of package either "active" or "deleted". + State *string `url:"state,omitempty"` + + ListOptions +} + +// PackageMetadata represents metadata from a package. +type PackageMetadata struct { + PackageType *string `json:"package_type,omitempty"` + Container *PackageContainerMetadata `json:"container,omitempty"` +} + +func (r PackageMetadata) String() string { + return Stringify(r) +} + +// PackageContainerMetadata represents container metadata for docker container packages. +type PackageContainerMetadata struct { + Tags []string `json:"tags,omitempty"` +} + +func (r PackageContainerMetadata) String() string { + return Stringify(r) +} diff --git a/vendor/github.com/google/go-github/v45/github/projects.go b/vendor/github.com/google/go-github/v45/github/projects.go new file mode 100644 index 0000000000..df7ad6cd97 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/projects.go @@ -0,0 +1,596 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ProjectsService provides access to the projects functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/projects +type ProjectsService service + +// Project represents a GitHub Project. +type Project struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + ColumnsURL *string `json:"columns_url,omitempty"` + OwnerURL *string `json:"owner_url,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` + OrganizationPermission *string `json:"organization_permission,omitempty"` + Private *bool `json:"private,omitempty"` + + // The User object that generated the project. + Creator *User `json:"creator,omitempty"` +} + +func (p Project) String() string { + return Stringify(p) +} + +// GetProject gets a GitHub Project for a repo. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#get-a-project +func (s *ProjectsService) GetProject(ctx context.Context, id int64) (*Project, *Response, error) { + u := fmt.Sprintf("projects/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} + +// ProjectOptions specifies the parameters to the +// RepositoriesService.CreateProject and +// ProjectsService.UpdateProject methods. +type ProjectOptions struct { + // The name of the project. (Required for creation; optional for update.) + Name *string `json:"name,omitempty"` + // The body of the project. (Optional.) + Body *string `json:"body,omitempty"` + + // The following field(s) are only applicable for update. + // They should be left with zero values for creation. + + // State of the project. Either "open" or "closed". (Optional.) + State *string `json:"state,omitempty"` + // The permission level that all members of the project's organization + // will have on this project. + // Setting the organization permission is only available + // for organization projects. (Optional.) + OrganizationPermission *string `json:"organization_permission,omitempty"` + // Sets visibility of the project within the organization. + // Setting visibility is only available + // for organization projects.(Optional.) + Private *bool `json:"private,omitempty"` +} + +// UpdateProject updates a repository project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#update-a-project +func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opts *ProjectOptions) (*Project, *Response, error) { + u := fmt.Sprintf("projects/%v", id) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} + +// DeleteProject deletes a GitHub Project from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#delete-a-project +func (s *ProjectsService) DeleteProject(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("projects/%v", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectColumn represents a column of a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/projects/ +type ProjectColumn struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + ProjectURL *string `json:"project_url,omitempty"` + CardsURL *string `json:"cards_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// ListProjectColumns lists the columns of a GitHub Project for a repo. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/columns#list-project-columns +func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opts *ListOptions) ([]*ProjectColumn, *Response, error) { + u := fmt.Sprintf("projects/%v/columns", projectID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + columns := []*ProjectColumn{} + resp, err := s.client.Do(ctx, req, &columns) + if err != nil { + return nil, resp, err + } + + return columns, resp, nil +} + +// GetProjectColumn gets a column of a GitHub Project for a repo. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/columns#get-a-project-column +func (s *ProjectsService) GetProjectColumn(ctx context.Context, id int64) (*ProjectColumn, *Response, error) { + u := fmt.Sprintf("projects/columns/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + column := &ProjectColumn{} + resp, err := s.client.Do(ctx, req, column) + if err != nil { + return nil, resp, err + } + + return column, resp, nil +} + +// ProjectColumnOptions specifies the parameters to the +// ProjectsService.CreateProjectColumn and +// ProjectsService.UpdateProjectColumn methods. +type ProjectColumnOptions struct { + // The name of the project column. (Required for creation and update.) + Name string `json:"name"` +} + +// CreateProjectColumn creates a column for the specified (by number) project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/columns#create-a-project-column +func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opts *ProjectColumnOptions) (*ProjectColumn, *Response, error) { + u := fmt.Sprintf("projects/%v/columns", projectID) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + column := &ProjectColumn{} + resp, err := s.client.Do(ctx, req, column) + if err != nil { + return nil, resp, err + } + + return column, resp, nil +} + +// UpdateProjectColumn updates a column of a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/columns#update-an-existing-project-column +func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opts *ProjectColumnOptions) (*ProjectColumn, *Response, error) { + u := fmt.Sprintf("projects/columns/%v", columnID) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + column := &ProjectColumn{} + resp, err := s.client.Do(ctx, req, column) + if err != nil { + return nil, resp, err + } + + return column, resp, nil +} + +// DeleteProjectColumn deletes a column from a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/columns#delete-a-project-column +func (s *ProjectsService) DeleteProjectColumn(ctx context.Context, columnID int64) (*Response, error) { + u := fmt.Sprintf("projects/columns/%v", columnID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectColumnMoveOptions specifies the parameters to the +// ProjectsService.MoveProjectColumn method. +type ProjectColumnMoveOptions struct { + // Position can be one of "first", "last", or "after:", where + // is the ID of a column in the same project. (Required.) + Position string `json:"position"` +} + +// MoveProjectColumn moves a column within a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/columns#move-a-project-column +func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opts *ProjectColumnMoveOptions) (*Response, error) { + u := fmt.Sprintf("projects/columns/%v/moves", columnID) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectCard represents a card in a column of a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/cards/#get-a-project-card +type ProjectCard struct { + URL *string `json:"url,omitempty"` + ColumnURL *string `json:"column_url,omitempty"` + ContentURL *string `json:"content_url,omitempty"` + ID *int64 `json:"id,omitempty"` + Note *string `json:"note,omitempty"` + Creator *User `json:"creator,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Archived *bool `json:"archived,omitempty"` + + // The following fields are only populated by Webhook events. + ColumnID *int64 `json:"column_id,omitempty"` + + // The following fields are only populated by Events API. + ProjectID *int64 `json:"project_id,omitempty"` + ProjectURL *string `json:"project_url,omitempty"` + ColumnName *string `json:"column_name,omitempty"` + PreviousColumnName *string `json:"previous_column_name,omitempty"` // Populated in "moved_columns_in_project" event deliveries. +} + +// ProjectCardListOptions specifies the optional parameters to the +// ProjectsService.ListProjectCards method. +type ProjectCardListOptions struct { + // ArchivedState is used to list all, archived, or not_archived project cards. + // Defaults to not_archived when you omit this parameter. + ArchivedState *string `url:"archived_state,omitempty"` + + ListOptions +} + +// ListProjectCards lists the cards in a column of a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/cards#list-project-cards +func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opts *ProjectCardListOptions) ([]*ProjectCard, *Response, error) { + u := fmt.Sprintf("projects/columns/%v/cards", columnID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + cards := []*ProjectCard{} + resp, err := s.client.Do(ctx, req, &cards) + if err != nil { + return nil, resp, err + } + + return cards, resp, nil +} + +// GetProjectCard gets a card in a column of a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/cards#get-a-project-card +func (s *ProjectsService) GetProjectCard(ctx context.Context, cardID int64) (*ProjectCard, *Response, error) { + u := fmt.Sprintf("projects/columns/cards/%v", cardID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + card := &ProjectCard{} + resp, err := s.client.Do(ctx, req, card) + if err != nil { + return nil, resp, err + } + + return card, resp, nil +} + +// ProjectCardOptions specifies the parameters to the +// ProjectsService.CreateProjectCard and +// ProjectsService.UpdateProjectCard methods. +type ProjectCardOptions struct { + // The note of the card. Note and ContentID are mutually exclusive. + Note string `json:"note,omitempty"` + // The ID (not Number) of the Issue to associate with this card. + // Note and ContentID are mutually exclusive. + ContentID int64 `json:"content_id,omitempty"` + // The type of content to associate with this card. Possible values are: "Issue" and "PullRequest". + ContentType string `json:"content_type,omitempty"` + // Use true to archive a project card. + // Specify false if you need to restore a previously archived project card. + Archived *bool `json:"archived,omitempty"` +} + +// CreateProjectCard creates a card in the specified column of a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/cards#create-a-project-card +func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opts *ProjectCardOptions) (*ProjectCard, *Response, error) { + u := fmt.Sprintf("projects/columns/%v/cards", columnID) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + card := &ProjectCard{} + resp, err := s.client.Do(ctx, req, card) + if err != nil { + return nil, resp, err + } + + return card, resp, nil +} + +// UpdateProjectCard updates a card of a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/cards#update-an-existing-project-card +func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opts *ProjectCardOptions) (*ProjectCard, *Response, error) { + u := fmt.Sprintf("projects/columns/cards/%v", cardID) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + card := &ProjectCard{} + resp, err := s.client.Do(ctx, req, card) + if err != nil { + return nil, resp, err + } + + return card, resp, nil +} + +// DeleteProjectCard deletes a card from a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/cards#delete-a-project-card +func (s *ProjectsService) DeleteProjectCard(ctx context.Context, cardID int64) (*Response, error) { + u := fmt.Sprintf("projects/columns/cards/%v", cardID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectCardMoveOptions specifies the parameters to the +// ProjectsService.MoveProjectCard method. +type ProjectCardMoveOptions struct { + // Position can be one of "top", "bottom", or "after:", where + // is the ID of a card in the same project. + Position string `json:"position"` + // ColumnID is the ID of a column in the same project. Note that ColumnID + // is required when using Position "after:" when that card is in + // another column; otherwise it is optional. + ColumnID int64 `json:"column_id,omitempty"` +} + +// MoveProjectCard moves a card within a GitHub Project. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/cards#move-a-project-card +func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opts *ProjectCardMoveOptions) (*Response, error) { + u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ProjectCollaboratorOptions specifies the optional parameters to the +// ProjectsService.AddProjectCollaborator method. +type ProjectCollaboratorOptions struct { + // Permission specifies the permission to grant to the collaborator. + // Possible values are: + // "read" - can read, but not write to or administer this project. + // "write" - can read and write, but not administer this project. + // "admin" - can read, write and administer this project. + // + // Default value is "write" + Permission *string `json:"permission,omitempty"` +} + +// AddProjectCollaborator adds a collaborator to an organization project and sets +// their permission level. You must be an organization owner or a project admin to add a collaborator. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/collaborators#add-project-collaborator +func (s *ProjectsService) AddProjectCollaborator(ctx context.Context, id int64, username string, opts *ProjectCollaboratorOptions) (*Response, error) { + u := fmt.Sprintf("projects/%v/collaborators/%v", id, username) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// RemoveProjectCollaborator removes a collaborator from an organization project. +// You must be an organization owner or a project admin to remove a collaborator. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/collaborators#remove-user-as-a-collaborator +func (s *ProjectsService) RemoveProjectCollaborator(ctx context.Context, id int64, username string) (*Response, error) { + u := fmt.Sprintf("projects/%v/collaborators/%v", id, username) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + return s.client.Do(ctx, req, nil) +} + +// ListCollaboratorOptions specifies the optional parameters to the +// ProjectsService.ListProjectCollaborators method. +type ListCollaboratorOptions struct { + // Affiliation specifies how collaborators should be filtered by their affiliation. + // Possible values are: + // "outside" - All outside collaborators of an organization-owned repository + // "direct" - All collaborators with permissions to an organization-owned repository, + // regardless of organization membership status + // "all" - All collaborators the authenticated user can see + // + // Default value is "all". + Affiliation *string `url:"affiliation,omitempty"` + + ListOptions +} + +// ListProjectCollaborators lists the collaborators for an organization project. For a project, +// the list of collaborators includes outside collaborators, organization members that are direct +// collaborators, organization members with access through team memberships, organization members +// with access through default organization permissions, and organization owners. You must be an +// organization owner or a project admin to list collaborators. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/collaborators#list-project-collaborators +func (s *ProjectsService) ListProjectCollaborators(ctx context.Context, id int64, opts *ListCollaboratorOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("projects/%v/collaborators", id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ProjectPermissionLevel represents the permission level an organization +// member has for a given project. +type ProjectPermissionLevel struct { + // Possible values: "admin", "write", "read", "none" + Permission *string `json:"permission,omitempty"` + + User *User `json:"user,omitempty"` +} + +// ReviewProjectCollaboratorPermission returns the collaborator's permission level for an organization +// project. Possible values for the permission key: "admin", "write", "read", "none". +// You must be an organization owner or a project admin to review a user's permission level. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/collaborators#get-project-permission-for-a-user +func (s *ProjectsService) ReviewProjectCollaboratorPermission(ctx context.Context, id int64, username string) (*ProjectPermissionLevel, *Response, error) { + u := fmt.Sprintf("projects/%v/collaborators/%v/permission", id, username) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + ppl := new(ProjectPermissionLevel) + resp, err := s.client.Do(ctx, req, ppl) + if err != nil { + return nil, resp, err + } + return ppl, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/pulls.go b/vendor/github.com/google/go-github/v45/github/pulls.go new file mode 100644 index 0000000000..120a1d6f18 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/pulls.go @@ -0,0 +1,486 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "time" +) + +// PullRequestsService handles communication with the pull request related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/ +type PullRequestsService service + +// PullRequestAutoMerge represents the "auto_merge" response for a PullRequest. +type PullRequestAutoMerge struct { + EnabledBy *User `json:"enabled_by,omitempty"` + MergeMethod *string `json:"merge_method,omitempty"` + CommitTitle *string `json:"commit_title,omitempty"` + CommitMessage *string `json:"commit_message,omitempty"` +} + +// PullRequest represents a GitHub pull request on a repository. +type PullRequest struct { + ID *int64 `json:"id,omitempty"` + Number *int `json:"number,omitempty"` + State *string `json:"state,omitempty"` + Locked *bool `json:"locked,omitempty"` + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + ClosedAt *time.Time `json:"closed_at,omitempty"` + MergedAt *time.Time `json:"merged_at,omitempty"` + Labels []*Label `json:"labels,omitempty"` + User *User `json:"user,omitempty"` + Draft *bool `json:"draft,omitempty"` + Merged *bool `json:"merged,omitempty"` + Mergeable *bool `json:"mergeable,omitempty"` + MergeableState *string `json:"mergeable_state,omitempty"` + MergedBy *User `json:"merged_by,omitempty"` + MergeCommitSHA *string `json:"merge_commit_sha,omitempty"` + Rebaseable *bool `json:"rebaseable,omitempty"` + Comments *int `json:"comments,omitempty"` + Commits *int `json:"commits,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + ChangedFiles *int `json:"changed_files,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + IssueURL *string `json:"issue_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + ReviewCommentsURL *string `json:"review_comments_url,omitempty"` + ReviewCommentURL *string `json:"review_comment_url,omitempty"` + ReviewComments *int `json:"review_comments,omitempty"` + Assignee *User `json:"assignee,omitempty"` + Assignees []*User `json:"assignees,omitempty"` + Milestone *Milestone `json:"milestone,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + AuthorAssociation *string `json:"author_association,omitempty"` + NodeID *string `json:"node_id,omitempty"` + RequestedReviewers []*User `json:"requested_reviewers,omitempty"` + AutoMerge *PullRequestAutoMerge `json:"auto_merge,omitempty"` + + // RequestedTeams is populated as part of the PullRequestEvent. + // See, https://docs.github.com/en/developers/webhooks-and-events/github-event-types#pullrequestevent for an example. + RequestedTeams []*Team `json:"requested_teams,omitempty"` + + Links *PRLinks `json:"_links,omitempty"` + Head *PullRequestBranch `json:"head,omitempty"` + Base *PullRequestBranch `json:"base,omitempty"` + + // ActiveLockReason is populated only when LockReason is provided while locking the pull request. + // Possible values are: "off-topic", "too heated", "resolved", and "spam". + ActiveLockReason *string `json:"active_lock_reason,omitempty"` +} + +func (p PullRequest) String() string { + return Stringify(p) +} + +// PRLink represents a single link object from GitHub pull request _links. +type PRLink struct { + HRef *string `json:"href,omitempty"` +} + +// PRLinks represents the "_links" object in a GitHub pull request. +type PRLinks struct { + Self *PRLink `json:"self,omitempty"` + HTML *PRLink `json:"html,omitempty"` + Issue *PRLink `json:"issue,omitempty"` + Comments *PRLink `json:"comments,omitempty"` + ReviewComments *PRLink `json:"review_comments,omitempty"` + ReviewComment *PRLink `json:"review_comment,omitempty"` + Commits *PRLink `json:"commits,omitempty"` + Statuses *PRLink `json:"statuses,omitempty"` +} + +// PullRequestBranch represents a base or head branch in a GitHub pull request. +type PullRequestBranch struct { + Label *string `json:"label,omitempty"` + Ref *string `json:"ref,omitempty"` + SHA *string `json:"sha,omitempty"` + Repo *Repository `json:"repo,omitempty"` + User *User `json:"user,omitempty"` +} + +// PullRequestListOptions specifies the optional parameters to the +// PullRequestsService.List method. +type PullRequestListOptions struct { + // State filters pull requests based on their state. Possible values are: + // open, closed, all. Default is "open". + State string `url:"state,omitempty"` + + // Head filters pull requests by head user and branch name in the format of: + // "user:ref-name". + Head string `url:"head,omitempty"` + + // Base filters pull requests by base branch name. + Base string `url:"base,omitempty"` + + // Sort specifies how to sort pull requests. Possible values are: created, + // updated, popularity, long-running. Default is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort pull requests. Possible values are: asc, desc. + // If Sort is "created" or not specified, Default is "desc", otherwise Default + // is "asc" + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// List the pull requests for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#list-pull-requests +func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opts *PullRequestListOptions) ([]*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pulls []*PullRequest + resp, err := s.client.Do(ctx, req, &pulls) + if err != nil { + return nil, resp, err + } + + return pulls, resp, nil +} + +// ListPullRequestsWithCommit returns pull requests associated with a commit SHA. +// +// The results may include open and closed pull requests. +// By default, the PullRequestListOptions State filters for "open". +// +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#list-pull-requests-associated-with-a-commit +func (s *PullRequestsService) ListPullRequestsWithCommit(ctx context.Context, owner, repo, sha string, opts *PullRequestListOptions) ([]*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/pulls", owner, repo, sha) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview) + var pulls []*PullRequest + resp, err := s.client.Do(ctx, req, &pulls) + if err != nil { + return nil, resp, err + } + + return pulls, resp, nil +} + +// Get a single pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#get-a-pull-request +func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + pull := new(PullRequest) + resp, err := s.client.Do(ctx, req, pull) + if err != nil { + return nil, resp, err + } + + return pull, resp, nil +} + +// GetRaw gets a single pull request in raw (diff or patch) format. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#get-a-pull-request +func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opts RawOptions) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opts.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// NewPullRequest represents a new pull request to be created. +type NewPullRequest struct { + Title *string `json:"title,omitempty"` + Head *string `json:"head,omitempty"` + Base *string `json:"base,omitempty"` + Body *string `json:"body,omitempty"` + Issue *int `json:"issue,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` + Draft *bool `json:"draft,omitempty"` +} + +// Create a new pull request on the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#create-a-pull-request +func (s *PullRequestsService) Create(ctx context.Context, owner string, repo string, pull *NewPullRequest) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo) + req, err := s.client.NewRequest("POST", u, pull) + if err != nil { + return nil, nil, err + } + + p := new(PullRequest) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// PullRequestBranchUpdateOptions specifies the optional parameters to the +// PullRequestsService.UpdateBranch method. +type PullRequestBranchUpdateOptions struct { + // ExpectedHeadSHA specifies the most recent commit on the pull request's branch. + // Default value is the SHA of the pull request's current HEAD ref. + ExpectedHeadSHA *string `json:"expected_head_sha,omitempty"` +} + +// PullRequestBranchUpdateResponse specifies the response of pull request branch update. +type PullRequestBranchUpdateResponse struct { + Message *string `json:"message,omitempty"` + URL *string `json:"url,omitempty"` +} + +// UpdateBranch updates the pull request branch with latest upstream changes. +// +// This method might return an AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it has now scheduled the update of the pull request branch in a background task. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#update-a-pull-request-branch +func (s *PullRequestsService) UpdateBranch(ctx context.Context, owner, repo string, number int, opts *PullRequestBranchUpdateOptions) (*PullRequestBranchUpdateResponse, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/update-branch", owner, repo, number) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeUpdatePullRequestBranchPreview) + + p := new(PullRequestBranchUpdateResponse) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +type pullRequestUpdate struct { + Title *string `json:"title,omitempty"` + Body *string `json:"body,omitempty"` + State *string `json:"state,omitempty"` + Base *string `json:"base,omitempty"` + MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"` +} + +// Edit a pull request. +// pull must not be nil. +// +// The following fields are editable: Title, Body, State, Base.Ref and MaintainerCanModify. +// Base.Ref updates the base branch of the pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#update-a-pull-request +func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo string, number int, pull *PullRequest) (*PullRequest, *Response, error) { + if pull == nil { + return nil, nil, fmt.Errorf("pull must be provided") + } + + u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number) + + update := &pullRequestUpdate{ + Title: pull.Title, + Body: pull.Body, + State: pull.State, + MaintainerCanModify: pull.MaintainerCanModify, + } + // avoid updating the base branch when closing the Pull Request + // - otherwise the GitHub API server returns a "Validation Failed" error: + // "Cannot change base branch of closed pull request". + if pull.Base != nil && pull.GetState() != "closed" { + update.Base = pull.Base.Ref + } + + req, err := s.client.NewRequest("PATCH", u, update) + if err != nil { + return nil, nil, err + } + + p := new(PullRequest) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// ListCommits lists the commits in a pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#list-commits-on-a-pull-request +func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commits []*RepositoryCommit + resp, err := s.client.Do(ctx, req, &commits) + if err != nil { + return nil, resp, err + } + + return commits, resp, nil +} + +// ListFiles lists the files in a pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#list-pull-requests-files +func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*CommitFile, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commitFiles []*CommitFile + resp, err := s.client.Do(ctx, req, &commitFiles) + if err != nil { + return nil, resp, err + } + + return commitFiles, resp, nil +} + +// IsMerged checks if a pull request has been merged. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#check-if-a-pull-request-has-been-merged +func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + merged, err := parseBoolResponse(err) + return merged, resp, err +} + +// PullRequestMergeResult represents the result of merging a pull request. +type PullRequestMergeResult struct { + SHA *string `json:"sha,omitempty"` + Merged *bool `json:"merged,omitempty"` + Message *string `json:"message,omitempty"` +} + +// PullRequestOptions lets you define how a pull request will be merged. +type PullRequestOptions struct { + CommitTitle string // Title for the automatic commit message. (Optional.) + SHA string // SHA that pull request head must match to allow merge. (Optional.) + + // The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.) + MergeMethod string + + // If false, an empty string commit message will use the default commit message. If true, an empty string commit message will be used. + DontDefaultIfBlank bool +} + +type pullRequestMergeRequest struct { + CommitMessage *string `json:"commit_message,omitempty"` + CommitTitle string `json:"commit_title,omitempty"` + MergeMethod string `json:"merge_method,omitempty"` + SHA string `json:"sha,omitempty"` +} + +// Merge a pull request. +// commitMessage is an extra detail to append to automatic commit message. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/pulls#merge-a-pull-request +func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number) + + pullRequestBody := &pullRequestMergeRequest{} + if commitMessage != "" { + pullRequestBody.CommitMessage = &commitMessage + } + if options != nil { + pullRequestBody.CommitTitle = options.CommitTitle + pullRequestBody.MergeMethod = options.MergeMethod + pullRequestBody.SHA = options.SHA + if options.DontDefaultIfBlank && commitMessage == "" { + pullRequestBody.CommitMessage = &commitMessage + } + } + req, err := s.client.NewRequest("PUT", u, pullRequestBody) + if err != nil { + return nil, nil, err + } + + mergeResult := new(PullRequestMergeResult) + resp, err := s.client.Do(ctx, req, mergeResult) + if err != nil { + return nil, resp, err + } + + return mergeResult, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/pulls_comments.go b/vendor/github.com/google/go-github/v45/github/pulls_comments.go new file mode 100644 index 0000000000..83e7881e51 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/pulls_comments.go @@ -0,0 +1,202 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strings" + "time" +) + +// PullRequestComment represents a comment left on a pull request. +type PullRequestComment struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + InReplyTo *int64 `json:"in_reply_to_id,omitempty"` + Body *string `json:"body,omitempty"` + Path *string `json:"path,omitempty"` + DiffHunk *string `json:"diff_hunk,omitempty"` + PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"` + Position *int `json:"position,omitempty"` + OriginalPosition *int `json:"original_position,omitempty"` + StartLine *int `json:"start_line,omitempty"` + Line *int `json:"line,omitempty"` + OriginalLine *int `json:"original_line,omitempty"` + OriginalStartLine *int `json:"original_start_line,omitempty"` + Side *string `json:"side,omitempty"` + StartSide *string `json:"start_side,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + OriginalCommitID *string `json:"original_commit_id,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + // AuthorAssociation is the comment author's relationship to the pull request's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequestURL *string `json:"pull_request_url,omitempty"` +} + +func (p PullRequestComment) String() string { + return Stringify(p) +} + +// PullRequestListCommentsOptions specifies the optional parameters to the +// PullRequestsService.ListComments method. +type PullRequestListCommentsOptions struct { + // Sort specifies how to sort comments. Possible values are: created, updated. + Sort string `url:"sort,omitempty"` + + // Direction in which to sort comments. Possible values are: asc, desc. + Direction string `url:"direction,omitempty"` + + // Since filters comments by time. + Since time.Time `url:"since,omitempty"` + + ListOptions +} + +// ListComments lists all comments on the specified pull request. Specifying a +// pull request number of 0 will return all comments on all pull requests for +// the repository. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/comments#list-review-comments-on-a-pull-request +// GitHub API docs: https://docs.github.com/en/rest/pulls/comments#list-review-comments-in-a-repository +func (s *PullRequestsService) ListComments(ctx context.Context, owner, repo string, number int, opts *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) { + var u string + if number == 0 { + u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo) + } else { + u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var comments []*PullRequestComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetComment fetches the specified pull request comment. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/comments#get-a-review-comment-for-a-pull-request +func (s *PullRequestsService) GetComment(ctx context.Context, owner, repo string, commentID int64) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + comment := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, comment) + if err != nil { + return nil, resp, err + } + + return comment, resp, nil +} + +// CreateComment creates a new comment on the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/comments#create-a-review-comment-for-a-pull-request +func (s *PullRequestsService) CreateComment(ctx context.Context, owner, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + // TODO: remove custom Accept headers when their respective API fully launches. + acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + c := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// CreateCommentInReplyTo creates a new comment as a reply to an existing pull request comment. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/comments#create-a-review-comment-for-a-pull-request +func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) { + comment := &struct { + Body string `json:"body,omitempty"` + InReplyTo int64 `json:"in_reply_to,omitempty"` + }{ + Body: body, + InReplyTo: commentID, + } + u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// EditComment updates a pull request comment. +// A non-nil comment.Body must be provided. Other comment fields should be left nil. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/comments#update-a-review-comment-for-a-pull-request +func (s *PullRequestsService) EditComment(ctx context.Context, owner, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(PullRequestComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a pull request comment. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/comments#delete-a-review-comment-for-a-pull-request +func (s *PullRequestsService) DeleteComment(ctx context.Context, owner, repo string, commentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/pulls_reviewers.go b/vendor/github.com/google/go-github/v45/github/pulls_reviewers.go new file mode 100644 index 0000000000..1c336540b8 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/pulls_reviewers.go @@ -0,0 +1,80 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ReviewersRequest specifies users and teams for a pull request review request. +type ReviewersRequest struct { + NodeID *string `json:"node_id,omitempty"` + Reviewers []string `json:"reviewers,omitempty"` + TeamReviewers []string `json:"team_reviewers,omitempty"` +} + +// Reviewers represents reviewers of a pull request. +type Reviewers struct { + Users []*User `json:"users,omitempty"` + Teams []*Team `json:"teams,omitempty"` +} + +// RequestReviewers creates a review request for the provided reviewers for the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/review-requests#request-reviewers-for-a-pull-request +func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) + req, err := s.client.NewRequest("POST", u, &reviewers) + if err != nil { + return nil, nil, err + } + + r := new(PullRequest) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// ListReviewers lists reviewers whose reviews have been requested on the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/review-requests#list-requested-reviewers-for-a-pull-request +func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opts *ListOptions) (*Reviewers, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + reviewers := new(Reviewers) + resp, err := s.client.Do(ctx, req, reviewers) + if err != nil { + return nil, resp, err + } + + return reviewers, resp, nil +} + +// RemoveReviewers removes the review request for the provided reviewers for the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/review-requests#remove-requested-reviewers-from-a-pull-request +func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number) + req, err := s.client.NewRequest("DELETE", u, &reviewers) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/pulls_reviews.go b/vendor/github.com/google/go-github/v45/github/pulls_reviews.go new file mode 100644 index 0000000000..14e20322ae --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/pulls_reviews.go @@ -0,0 +1,312 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "time" +) + +var ErrMixedCommentStyles = errors.New("cannot use both position and side/line form comments") + +// PullRequestReview represents a review of a pull request. +type PullRequestReview struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + User *User `json:"user,omitempty"` + Body *string `json:"body,omitempty"` + SubmittedAt *time.Time `json:"submitted_at,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + PullRequestURL *string `json:"pull_request_url,omitempty"` + State *string `json:"state,omitempty"` + // AuthorAssociation is the comment author's relationship to the issue's repository. + // Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE". + AuthorAssociation *string `json:"author_association,omitempty"` +} + +func (p PullRequestReview) String() string { + return Stringify(p) +} + +// DraftReviewComment represents a comment part of the review. +type DraftReviewComment struct { + Path *string `json:"path,omitempty"` + Position *int `json:"position,omitempty"` + Body *string `json:"body,omitempty"` + + // The new comfort-fade-preview fields + StartSide *string `json:"start_side,omitempty"` + Side *string `json:"side,omitempty"` + StartLine *int `json:"start_line,omitempty"` + Line *int `json:"line,omitempty"` +} + +func (c DraftReviewComment) String() string { + return Stringify(c) +} + +// PullRequestReviewRequest represents a request to create a review. +type PullRequestReviewRequest struct { + NodeID *string `json:"node_id,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + Body *string `json:"body,omitempty"` + Event *string `json:"event,omitempty"` + Comments []*DraftReviewComment `json:"comments,omitempty"` +} + +func (r PullRequestReviewRequest) String() string { + return Stringify(r) +} + +func (r *PullRequestReviewRequest) isComfortFadePreview() (bool, error) { + var isCF *bool + for _, comment := range r.Comments { + if comment == nil { + continue + } + hasPos := comment.Position != nil + hasComfortFade := (comment.StartSide != nil) || (comment.Side != nil) || + (comment.StartLine != nil) || (comment.Line != nil) + + switch { + case hasPos && hasComfortFade: + return false, ErrMixedCommentStyles + case hasPos && isCF != nil && *isCF: + return false, ErrMixedCommentStyles + case hasComfortFade && isCF != nil && !*isCF: + return false, ErrMixedCommentStyles + } + isCF = &hasComfortFade + } + if isCF != nil { + return *isCF, nil + } + return false, nil +} + +// PullRequestReviewDismissalRequest represents a request to dismiss a review. +type PullRequestReviewDismissalRequest struct { + Message *string `json:"message,omitempty"` +} + +func (r PullRequestReviewDismissalRequest) String() string { + return Stringify(r) +} + +// ListReviews lists all reviews on the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/reviews#list-reviews-for-a-pull-request +func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var reviews []*PullRequestReview + resp, err := s.client.Do(ctx, req, &reviews) + if err != nil { + return nil, resp, err + } + + return reviews, resp, nil +} + +// GetReview fetches the specified pull request review. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/reviews#get-a-review-for-a-pull-request +func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + review := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + +// DeletePendingReview deletes the specified pull request pending review. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/reviews#delete-a-pending-review-for-a-pull-request +func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, nil, err + } + + review := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + +// ListReviewComments lists all the comments for the specified review. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/reviews#list-comments-for-a-pull-request-review +func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opts *ListOptions) ([]*PullRequestComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*PullRequestComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// CreateReview creates a new review on the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/reviews#create-a-review-for-a-pull-request +// +// In order to use multi-line comments, you must use the "comfort fade" preview. +// This replaces the use of the "Position" field in comments with 4 new fields: +// [Start]Side, and [Start]Line. +// These new fields must be used for ALL comments (including single-line), +// with the following restrictions (empirically observed, so subject to change). +// +// For single-line "comfort fade" comments, you must use: +// +// Path: &path, // as before +// Body: &body, // as before +// Side: &"RIGHT" (or "LEFT") +// Line: &123, // NOT THE SAME AS POSITION, this is an actual line number. +// +// If StartSide or StartLine is used with single-line comments, a 422 is returned. +// +// For multi-line "comfort fade" comments, you must use: +// +// Path: &path, // as before +// Body: &body, // as before +// StartSide: &"RIGHT" (or "LEFT") +// Side: &"RIGHT" (or "LEFT") +// StartLine: &120, +// Line: &125, +// +// Suggested edits are made by commenting on the lines to replace, and including the +// suggested edit in a block like this (it may be surrounded in non-suggestion markdown): +// +// ```suggestion +// Use this instead. +// It is waaaaaay better. +// ``` +func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number) + + req, err := s.client.NewRequest("POST", u, review) + if err != nil { + return nil, nil, err + } + + // Detect which style of review comment is being used. + if isCF, err := review.isComfortFadePreview(); err != nil { + return nil, nil, err + } else if isCF { + // If the review comments are using the comfort fade preview fields, + // then pass the comfort fade header. + req.Header.Set("Accept", mediaTypeMultiLineCommentsPreview) + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdateReview updates the review summary on the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/reviews#update-a-review-for-a-pull-request +func (s *PullRequestsService) UpdateReview(ctx context.Context, owner, repo string, number int, reviewID int64, body string) (*PullRequestReview, *Response, error) { + opts := &struct { + Body string `json:"body"` + }{Body: body} + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + review := &PullRequestReview{} + resp, err := s.client.Do(ctx, req, review) + if err != nil { + return nil, resp, err + } + + return review, resp, nil +} + +// SubmitReview submits a specified review on the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/reviews#submit-a-review-for-a-pull-request +func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("POST", u, review) + if err != nil { + return nil, nil, err + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DismissReview dismisses a specified review on the specified pull request. +// +// GitHub API docs: https://docs.github.com/en/rest/pulls/reviews#dismiss-a-review-for-a-pull-request +func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID) + + req, err := s.client.NewRequest("PUT", u, review) + if err != nil { + return nil, nil, err + } + + r := new(PullRequestReview) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/pulls_threads.go b/vendor/github.com/google/go-github/v45/github/pulls_threads.go new file mode 100644 index 0000000000..23e924d88f --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/pulls_threads.go @@ -0,0 +1,17 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +// PullRequestThread represents a thread of comments on a pull request. +type PullRequestThread struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Comments []*PullRequestComment `json:"comments,omitempty"` +} + +func (p PullRequestThread) String() string { + return Stringify(p) +} diff --git a/vendor/github.com/google/go-github/v45/github/reactions.go b/vendor/github.com/google/go-github/v45/github/reactions.go new file mode 100644 index 0000000000..14d193ae88 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/reactions.go @@ -0,0 +1,520 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" +) + +// ReactionsService provides access to the reactions-related functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions +type ReactionsService service + +// Reaction represents a GitHub reaction. +type Reaction struct { + // ID is the Reaction ID. + ID *int64 `json:"id,omitempty"` + User *User `json:"user,omitempty"` + NodeID *string `json:"node_id,omitempty"` + // Content is the type of reaction. + // Possible values are: + // "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". + Content *string `json:"content,omitempty"` +} + +// Reactions represents a summary of GitHub reactions. +type Reactions struct { + TotalCount *int `json:"total_count,omitempty"` + PlusOne *int `json:"+1,omitempty"` + MinusOne *int `json:"-1,omitempty"` + Laugh *int `json:"laugh,omitempty"` + Confused *int `json:"confused,omitempty"` + Heart *int `json:"heart,omitempty"` + Hooray *int `json:"hooray,omitempty"` + Rocket *int `json:"rocket,omitempty"` + Eyes *int `json:"eyes,omitempty"` + URL *string `json:"url,omitempty"` +} + +func (r Reaction) String() string { + return Stringify(r) +} + +// ListCommentReactionOptions specifies the optional parameters to the +// ReactionsService.ListCommentReactions method. +type ListCommentReactionOptions struct { + // Content restricts the returned comment reactions to only those with the given type. + // Omit this parameter to list all reactions to a commit comment. + // Possible values are: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". + Content string `url:"content,omitempty"` + + ListOptions +} + +// ListCommentReactions lists the reactions for a commit comment. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#list-reactions-for-a-commit-comment +func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListCommentReactionOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateCommentReaction creates a reaction for a commit comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-a-commit-comment +func (s *ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteCommentReaction deletes the reaction for a commit comment. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-a-commit-comment-reaction +func (s *ReactionsService) DeleteCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, u) +} + +// DeleteCommentReactionByID deletes the reaction for a commit comment by repository ID. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-a-commit-comment-reaction +func (s *ReactionsService) DeleteCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + u := fmt.Sprintf("repositories/%v/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, u) +} + +// ListIssueReactions lists the reactions for an issue. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#list-reactions-for-an-issue +func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueReaction creates a reaction for an issue. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-an-issue +func (s *ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteIssueReaction deletes the reaction to an issue. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-an-issue-reaction +func (s *ReactionsService) DeleteIssueReaction(ctx context.Context, owner, repo string, issueNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/issues/%v/reactions/%v", owner, repo, issueNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteIssueReactionByID deletes the reaction to an issue by repository ID. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-an-issue-reaction +func (s *ReactionsService) DeleteIssueReactionByID(ctx context.Context, repoID, issueNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/issues/%v/reactions/%v", repoID, issueNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListIssueCommentReactions lists the reactions for an issue comment. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#list-reactions-for-an-issue-comment +func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateIssueCommentReaction creates a reaction for an issue comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-an-issue-comment +func (s *ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteIssueCommentReaction deletes the reaction to an issue comment. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-an-issue-comment-reaction +func (s *ReactionsService) DeleteIssueCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteIssueCommentReactionByID deletes the reaction to an issue comment by repository ID. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-an-issue-comment-reaction +func (s *ReactionsService) DeleteIssueCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/issues/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListPullRequestCommentReactions lists the reactions for a pull request review comment. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#list-reactions-for-a-pull-request-review-comment +func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreatePullRequestCommentReaction creates a reaction for a pull request review comment. +// Note that if you have already created a reaction of type content, the +// previously created reaction will be returned with Status: 200 OK. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-a-pull-request-review-comment +func (s *ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeletePullRequestCommentReaction deletes the reaction to a pull request review comment. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-a-pull-request-comment-reaction +func (s *ReactionsService) DeletePullRequestCommentReaction(ctx context.Context, owner, repo string, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions/%v", owner, repo, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeletePullRequestCommentReactionByID deletes the reaction to a pull request review comment by repository ID. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-a-pull-request-comment-reaction +func (s *ReactionsService) DeletePullRequestCommentReactionByID(ctx context.Context, repoID, commentID, reactionID int64) (*Response, error) { + url := fmt.Sprintf("repositories/%v/pulls/comments/%v/reactions/%v", repoID, commentID, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListTeamDiscussionReactions lists the reactions for a team discussion. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#list-reactions-for-a-team-discussion-legacy +func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, teamID int64, discussionNumber int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// CreateTeamDiscussionReaction creates a reaction for a team discussion. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-a-team-discussion-legacy +func (s *ReactionsService) CreateTeamDiscussionReaction(ctx context.Context, teamID int64, discussionNumber int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteTeamDiscussionReaction deletes the reaction to a team discussion. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-team-discussion-reaction +func (s *ReactionsService) DeleteTeamDiscussionReaction(ctx context.Context, org, teamSlug string, discussionNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/reactions/%v", org, teamSlug, discussionNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteTeamDiscussionReactionByOrgIDAndTeamID deletes the reaction to a team discussion by organization ID and team ID. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-a-team-discussion +func (s *ReactionsService) DeleteTeamDiscussionReactionByOrgIDAndTeamID(ctx context.Context, orgID, teamID, discussionNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/reactions/%v", orgID, teamID, discussionNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// ListTeamDiscussionCommentReactions lists the reactions for a team discussion comment. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#list-reactions-for-a-team-discussion-comment-legacy +func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Context, teamID int64, discussionNumber, commentNumber int, opts *ListOptions) ([]*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var m []*Reaction + resp, err := s.client.Do(ctx, req, &m) + if err != nil { + return nil, resp, err + } + return m, resp, nil +} + +// CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-a-team-discussion-comment-legacy +func (s *ReactionsService) CreateTeamDiscussionCommentReaction(ctx context.Context, teamID int64, discussionNumber, commentNumber int, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} + +// DeleteTeamDiscussionCommentReaction deletes the reaction to a team discussion comment. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#delete-team-discussion-comment-reaction +func (s *ReactionsService) DeleteTeamDiscussionCommentReaction(ctx context.Context, org, teamSlug string, discussionNumber, commentNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v/reactions/%v", org, teamSlug, discussionNumber, commentNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +// DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID deletes the reaction to a team discussion comment by organization ID and team ID. +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-a-team-discussion-comment +func (s *ReactionsService) DeleteTeamDiscussionCommentReactionByOrgIDAndTeamID(ctx context.Context, orgID, teamID, discussionNumber, commentNumber int, reactionID int64) (*Response, error) { + url := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v/reactions/%v", orgID, teamID, discussionNumber, commentNumber, reactionID) + + return s.deleteReaction(ctx, url) +} + +func (s *ReactionsService) deleteReaction(ctx context.Context, url string) (*Response, error) { + req, err := s.client.NewRequest(http.MethodDelete, url, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + return s.client.Do(ctx, req, nil) +} + +// Create a reaction to a release. +// Note that a response with a Status: 200 OK means that you already +// added the reaction type to this release. +// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes". +// +// GitHub API docs: https://docs.github.com/en/rest/reactions#create-reaction-for-a-release +func (s *ReactionsService) CreateReleaseReaction(ctx context.Context, owner, repo string, releaseID int64, content string) (*Reaction, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/releases/%v/reactions", owner, repo, releaseID) + + body := &Reaction{Content: String(content)} + req, err := s.client.NewRequest("POST", u, body) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeReactionsPreview) + + m := &Reaction{} + resp, err := s.client.Do(ctx, req, m) + if err != nil { + return nil, resp, err + } + + return m, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos.go b/vendor/github.com/google/go-github/v45/github/repos.go new file mode 100644 index 0000000000..13e0887ea7 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos.go @@ -0,0 +1,1669 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "net/http" + "strings" +) + +const githubBranchNotProtected string = "Branch not protected" + +var ErrBranchNotProtected = errors.New("branch is not protected") + +// RepositoriesService handles communication with the repository related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/ +type RepositoriesService service + +// Repository represents a GitHub repository. +type Repository struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Owner *User `json:"owner,omitempty"` + Name *string `json:"name,omitempty"` + FullName *string `json:"full_name,omitempty"` + Description *string `json:"description,omitempty"` + Homepage *string `json:"homepage,omitempty"` + CodeOfConduct *CodeOfConduct `json:"code_of_conduct,omitempty"` + DefaultBranch *string `json:"default_branch,omitempty"` + MasterBranch *string `json:"master_branch,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PushedAt *Timestamp `json:"pushed_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CloneURL *string `json:"clone_url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + MirrorURL *string `json:"mirror_url,omitempty"` + SSHURL *string `json:"ssh_url,omitempty"` + SVNURL *string `json:"svn_url,omitempty"` + Language *string `json:"language,omitempty"` + Fork *bool `json:"fork,omitempty"` + ForksCount *int `json:"forks_count,omitempty"` + NetworkCount *int `json:"network_count,omitempty"` + OpenIssuesCount *int `json:"open_issues_count,omitempty"` + OpenIssues *int `json:"open_issues,omitempty"` // Deprecated: Replaced by OpenIssuesCount. For backward compatibility OpenIssues is still populated. + StargazersCount *int `json:"stargazers_count,omitempty"` + SubscribersCount *int `json:"subscribers_count,omitempty"` + WatchersCount *int `json:"watchers_count,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility WatchersCount is still populated. + Watchers *int `json:"watchers,omitempty"` // Deprecated: Replaced by StargazersCount. For backward compatibility Watchers is still populated. + Size *int `json:"size,omitempty"` + AutoInit *bool `json:"auto_init,omitempty"` + Parent *Repository `json:"parent,omitempty"` + Source *Repository `json:"source,omitempty"` + TemplateRepository *Repository `json:"template_repository,omitempty"` + Organization *Organization `json:"organization,omitempty"` + Permissions map[string]bool `json:"permissions,omitempty"` + AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` + AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"` + AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` + AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` + AllowAutoMerge *bool `json:"allow_auto_merge,omitempty"` + AllowForking *bool `json:"allow_forking,omitempty"` + DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"` + Topics []string `json:"topics,omitempty"` + Archived *bool `json:"archived,omitempty"` + Disabled *bool `json:"disabled,omitempty"` + + // Only provided when using RepositoriesService.Get while in preview + License *License `json:"license,omitempty"` + + // Additional mutable fields when creating and editing a repository + Private *bool `json:"private,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + HasPages *bool `json:"has_pages,omitempty"` + HasProjects *bool `json:"has_projects,omitempty"` + HasDownloads *bool `json:"has_downloads,omitempty"` + IsTemplate *bool `json:"is_template,omitempty"` + LicenseTemplate *string `json:"license_template,omitempty"` + GitignoreTemplate *string `json:"gitignore_template,omitempty"` + + // Options for configuring Advanced Security and Secret Scanning + SecurityAndAnalysis *SecurityAndAnalysis `json:"security_and_analysis,omitempty"` + + // Creating an organization repository. Required for non-owners. + TeamID *int64 `json:"team_id,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + ArchiveURL *string `json:"archive_url,omitempty"` + AssigneesURL *string `json:"assignees_url,omitempty"` + BlobsURL *string `json:"blobs_url,omitempty"` + BranchesURL *string `json:"branches_url,omitempty"` + CollaboratorsURL *string `json:"collaborators_url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + CommitsURL *string `json:"commits_url,omitempty"` + CompareURL *string `json:"compare_url,omitempty"` + ContentsURL *string `json:"contents_url,omitempty"` + ContributorsURL *string `json:"contributors_url,omitempty"` + DeploymentsURL *string `json:"deployments_url,omitempty"` + DownloadsURL *string `json:"downloads_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + ForksURL *string `json:"forks_url,omitempty"` + GitCommitsURL *string `json:"git_commits_url,omitempty"` + GitRefsURL *string `json:"git_refs_url,omitempty"` + GitTagsURL *string `json:"git_tags_url,omitempty"` + HooksURL *string `json:"hooks_url,omitempty"` + IssueCommentURL *string `json:"issue_comment_url,omitempty"` + IssueEventsURL *string `json:"issue_events_url,omitempty"` + IssuesURL *string `json:"issues_url,omitempty"` + KeysURL *string `json:"keys_url,omitempty"` + LabelsURL *string `json:"labels_url,omitempty"` + LanguagesURL *string `json:"languages_url,omitempty"` + MergesURL *string `json:"merges_url,omitempty"` + MilestonesURL *string `json:"milestones_url,omitempty"` + NotificationsURL *string `json:"notifications_url,omitempty"` + PullsURL *string `json:"pulls_url,omitempty"` + ReleasesURL *string `json:"releases_url,omitempty"` + StargazersURL *string `json:"stargazers_url,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + SubscribersURL *string `json:"subscribers_url,omitempty"` + SubscriptionURL *string `json:"subscription_url,omitempty"` + TagsURL *string `json:"tags_url,omitempty"` + TreesURL *string `json:"trees_url,omitempty"` + TeamsURL *string `json:"teams_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://docs.github.com/en/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` + + // Visibility is only used for Create and Edit endpoints. The visibility field + // overrides the field parameter when both are used. + // Can be one of public, private or internal. + Visibility *string `json:"visibility,omitempty"` +} + +func (r Repository) String() string { + return Stringify(r) +} + +// BranchListOptions specifies the optional parameters to the +// RepositoriesService.ListBranches method. +type BranchListOptions struct { + // Setting to true returns only protected branches. + // When set to false, only unprotected branches are returned. + // Omitting this parameter returns all branches. + // Default: nil + Protected *bool `url:"protected,omitempty"` + + ListOptions +} + +// RepositoryListOptions specifies the optional parameters to the +// RepositoriesService.List method. +type RepositoryListOptions struct { + // Visibility of repositories to list. Can be one of all, public, or private. + // Default: all + Visibility string `url:"visibility,omitempty"` + + // List repos of given affiliation[s]. + // Comma-separated list of values. Can include: + // * owner: Repositories that are owned by the authenticated user. + // * collaborator: Repositories that the user has been added to as a + // collaborator. + // * organization_member: Repositories that the user has access to through + // being a member of an organization. This includes every repository on + // every team that the user is on. + // Default: owner,collaborator,organization_member + Affiliation string `url:"affiliation,omitempty"` + + // Type of repositories to list. + // Can be one of all, owner, public, private, member. Default: all + // Will cause a 422 error if used in the same request as visibility or + // affiliation. + Type string `url:"type,omitempty"` + + // How to sort the repository list. Can be one of created, updated, pushed, + // full_name. Default: full_name + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Can be one of asc or desc. + // Default: when using full_name: asc; otherwise desc + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// SecurityAndAnalysis specifies the optional advanced security features +// that are enabled on a given repository. +type SecurityAndAnalysis struct { + AdvancedSecurity *AdvancedSecurity `json:"advanced_security,omitempty"` + SecretScanning *SecretScanning `json:"secret_scanning,omitempty"` +} + +func (s SecurityAndAnalysis) String() string { + return Stringify(s) +} + +// AdvancedSecurity specifies the state of advanced security on a repository. +// +// GitHub API docs: https://docs.github.com/en/github/getting-started-with-github/learning-about-github/about-github-advanced-security +type AdvancedSecurity struct { + Status *string `json:"status,omitempty"` +} + +func (a AdvancedSecurity) String() string { + return Stringify(a) +} + +// SecretScanning specifies the state of secret scanning on a repository. +// +// GitHub API docs: https://docs.github.com/en/code-security/secret-security/about-secret-scanning +type SecretScanning struct { + Status *string `json:"status,omitempty"` +} + +func (s SecretScanning) String() string { + return Stringify(s) +} + +// List the repositories for a user. Passing the empty string will list +// repositories for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repositories-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repositories-for-a-user +func (s *RepositoriesService) List(ctx context.Context, user string, opts *RepositoryListOptions) ([]*Repository, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/repos", user) + } else { + u = "user/repos" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListByOrgOptions specifies the optional parameters to the +// RepositoriesService.ListByOrg method. +type RepositoryListByOrgOptions struct { + // Type of repositories to list. Possible values are: all, public, private, + // forks, sources, member. Default is "all". + Type string `url:"type,omitempty"` + + // How to sort the repository list. Can be one of created, updated, pushed, + // full_name. Default is "created". + Sort string `url:"sort,omitempty"` + + // Direction in which to sort repositories. Can be one of asc or desc. + // Default when using full_name: asc; otherwise desc. + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListByOrg lists the repositories for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-organization-repositories +func (s *RepositoriesService) ListByOrg(ctx context.Context, org string, opts *RepositoryListByOrgOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/repos", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeTopicsPreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryListAllOptions specifies the optional parameters to the +// RepositoriesService.ListAll method. +type RepositoryListAllOptions struct { + // ID of the last repository seen + Since int64 `url:"since,omitempty"` +} + +// ListAll lists all GitHub repositories in the order that they were created. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-public-repositories +func (s *RepositoriesService) ListAll(ctx context.Context, opts *RepositoryListAllOptions) ([]*Repository, *Response, error) { + u, err := addOptions("repositories", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// createRepoRequest is a subset of Repository and is used internally +// by Create to pass only the known fields for the endpoint. +// +// See https://github.com/google/go-github/issues/1014 for more +// information. +type createRepoRequest struct { + // Name is required when creating a repo. + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Homepage *string `json:"homepage,omitempty"` + + Private *bool `json:"private,omitempty"` + Visibility *string `json:"visibility,omitempty"` + HasIssues *bool `json:"has_issues,omitempty"` + HasProjects *bool `json:"has_projects,omitempty"` + HasWiki *bool `json:"has_wiki,omitempty"` + IsTemplate *bool `json:"is_template,omitempty"` + + // Creating an organization repository. Required for non-owners. + TeamID *int64 `json:"team_id,omitempty"` + + AutoInit *bool `json:"auto_init,omitempty"` + GitignoreTemplate *string `json:"gitignore_template,omitempty"` + LicenseTemplate *string `json:"license_template,omitempty"` + AllowSquashMerge *bool `json:"allow_squash_merge,omitempty"` + AllowMergeCommit *bool `json:"allow_merge_commit,omitempty"` + AllowRebaseMerge *bool `json:"allow_rebase_merge,omitempty"` + AllowUpdateBranch *bool `json:"allow_update_branch,omitempty"` + AllowAutoMerge *bool `json:"allow_auto_merge,omitempty"` + AllowForking *bool `json:"allow_forking,omitempty"` + DeleteBranchOnMerge *bool `json:"delete_branch_on_merge,omitempty"` +} + +// Create a new repository. If an organization is specified, the new +// repository will be created under that org. If the empty string is +// specified, it will be created for the authenticated user. +// +// Note that only a subset of the repo fields are used and repo must +// not be nil. +// +// Also note that this method will return the response without actually +// waiting for GitHub to finish creating the repository and letting the +// changes propagate throughout its servers. You may set up a loop with +// exponential back-off to verify repository's creation. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-an-organization-repository +func (s *RepositoriesService) Create(ctx context.Context, org string, repo *Repository) (*Repository, *Response, error) { + var u string + if org != "" { + u = fmt.Sprintf("orgs/%v/repos", org) + } else { + u = "user/repos" + } + + repoReq := &createRepoRequest{ + Name: repo.Name, + Description: repo.Description, + Homepage: repo.Homepage, + Private: repo.Private, + Visibility: repo.Visibility, + HasIssues: repo.HasIssues, + HasProjects: repo.HasProjects, + HasWiki: repo.HasWiki, + IsTemplate: repo.IsTemplate, + TeamID: repo.TeamID, + AutoInit: repo.AutoInit, + GitignoreTemplate: repo.GitignoreTemplate, + LicenseTemplate: repo.LicenseTemplate, + AllowSquashMerge: repo.AllowSquashMerge, + AllowMergeCommit: repo.AllowMergeCommit, + AllowRebaseMerge: repo.AllowRebaseMerge, + AllowUpdateBranch: repo.AllowUpdateBranch, + AllowAutoMerge: repo.AllowAutoMerge, + AllowForking: repo.AllowForking, + DeleteBranchOnMerge: repo.DeleteBranchOnMerge, + } + + req, err := s.client.NewRequest("POST", u, repoReq) + if err != nil { + return nil, nil, err + } + + acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// TemplateRepoRequest represents a request to create a repository from a template. +type TemplateRepoRequest struct { + // Name is required when creating a repo. + Name *string `json:"name,omitempty"` + Owner *string `json:"owner,omitempty"` + Description *string `json:"description,omitempty"` + + IncludeAllBranches *bool `json:"include_all_branches,omitempty"` + Private *bool `json:"private,omitempty"` +} + +// CreateFromTemplate generates a repository from a template. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-using-a-template +func (s *RepositoriesService) CreateFromTemplate(ctx context.Context, templateOwner, templateRepo string, templateRepoReq *TemplateRepoRequest) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/generate", templateOwner, templateRepo) + + req, err := s.client.NewRequest("POST", u, templateRepoReq) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeRepositoryTemplatePreview) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// Get fetches a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#update-a-repository +func (s *RepositoriesService) Get(ctx context.Context, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when the license support fully launches + // https://docs.github.com/en/rest/licenses/#get-a-repositorys-license + acceptHeaders := []string{ + mediaTypeCodesOfConductPreview, + mediaTypeTopicsPreview, + mediaTypeRepositoryTemplatePreview, + mediaTypeRepositoryVisibilityPreview, + } + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// GetCodeOfConduct gets the contents of a repository's code of conduct. +// Note that https://docs.github.com/en/rest/codes-of-conduct#about-the-codes-of-conduct-api +// says to use the GET /repos/{owner}/{repo} endpoint. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#update-a-repository +func (s *RepositoriesService) GetCodeOfConduct(ctx context.Context, owner, repo string) (*CodeOfConduct, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCodesOfConductPreview) + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r.GetCodeOfConduct(), resp, nil +} + +// GetByID fetches a repository. +// +// Note: GetByID uses the undocumented GitHub API endpoint /repositories/:id. +func (s *RepositoriesService) GetByID(ctx context.Context, id int64) (*Repository, *Response, error) { + u := fmt.Sprintf("repositories/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// Edit updates a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#update-a-repository +func (s *RepositoriesService) Edit(ctx context.Context, owner, repo string, repository *Repository) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("PATCH", u, repository) + if err != nil { + return nil, nil, err + } + + acceptHeaders := []string{mediaTypeRepositoryTemplatePreview, mediaTypeRepositoryVisibilityPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// Delete a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#delete-a-repository +func (s *RepositoriesService) Delete(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Contributor represents a repository contributor +type Contributor struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + Contributions *int `json:"contributions,omitempty"` + Name *string `json:"name,omitempty"` + Email *string `json:"email,omitempty"` +} + +// ListContributorsOptions specifies the optional parameters to the +// RepositoriesService.ListContributors method. +type ListContributorsOptions struct { + // Include anonymous contributors in results or not + Anon string `url:"anon,omitempty"` + + ListOptions +} + +// GetVulnerabilityAlerts checks if vulnerability alerts are enabled for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#check-if-vulnerability-alerts-are-enabled-for-a-repository +func (s *RepositoriesService) GetVulnerabilityAlerts(ctx context.Context, owner, repository string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + resp, err := s.client.Do(ctx, req, nil) + vulnerabilityAlertsEnabled, err := parseBoolResponse(err) + return vulnerabilityAlertsEnabled, resp, err +} + +// EnableVulnerabilityAlerts enables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#enable-vulnerability-alerts +func (s *RepositoriesService) EnableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + return s.client.Do(ctx, req, nil) +} + +// DisableVulnerabilityAlerts disables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#disable-vulnerability-alerts +func (s *RepositoriesService) DisableVulnerabilityAlerts(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/vulnerability-alerts", owner, repository) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredVulnerabilityAlertsPreview) + + return s.client.Do(ctx, req, nil) +} + +// EnableAutomatedSecurityFixes enables the automated security fixes for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#enable-automated-security-fixes +func (s *RepositoriesService) EnableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview) + + return s.client.Do(ctx, req, nil) +} + +// DisableAutomatedSecurityFixes disables vulnerability alerts and the dependency graph for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#disable-automated-security-fixes +func (s *RepositoriesService) DisableAutomatedSecurityFixes(ctx context.Context, owner, repository string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/automated-security-fixes", owner, repository) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredAutomatedSecurityFixesPreview) + + return s.client.Do(ctx, req, nil) +} + +// ListContributors lists contributors for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-contributors +func (s *RepositoriesService) ListContributors(ctx context.Context, owner string, repository string, opts *ListContributorsOptions) ([]*Contributor, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/contributors", owner, repository) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var contributor []*Contributor + resp, err := s.client.Do(ctx, req, &contributor) + if err != nil { + return nil, resp, err + } + + return contributor, resp, nil +} + +// ListLanguages lists languages for the specified repository. The returned map +// specifies the languages and the number of bytes of code written in that +// language. For example: +// +// { +// "C": 78769, +// "Python": 7769 +// } +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-languages +func (s *RepositoriesService) ListLanguages(ctx context.Context, owner string, repo string) (map[string]int, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/languages", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + languages := make(map[string]int) + resp, err := s.client.Do(ctx, req, &languages) + if err != nil { + return nil, resp, err + } + + return languages, resp, nil +} + +// ListTeams lists the teams for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-teams +func (s *RepositoriesService) ListTeams(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/teams", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// RepositoryTag represents a repository tag. +type RepositoryTag struct { + Name *string `json:"name,omitempty"` + Commit *Commit `json:"commit,omitempty"` + ZipballURL *string `json:"zipball_url,omitempty"` + TarballURL *string `json:"tarball_url,omitempty"` +} + +// ListTags lists tags for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#list-repository-tags +func (s *RepositoriesService) ListTags(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*RepositoryTag, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/tags", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var tags []*RepositoryTag + resp, err := s.client.Do(ctx, req, &tags) + if err != nil { + return nil, resp, err + } + + return tags, resp, nil +} + +// Branch represents a repository branch +type Branch struct { + Name *string `json:"name,omitempty"` + Commit *RepositoryCommit `json:"commit,omitempty"` + Protected *bool `json:"protected,omitempty"` +} + +// Protection represents a repository branch's protection. +type Protection struct { + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcement `json:"required_pull_request_reviews"` + EnforceAdmins *AdminEnforcement `json:"enforce_admins"` + Restrictions *BranchRestrictions `json:"restrictions"` + RequireLinearHistory *RequireLinearHistory `json:"required_linear_history"` + AllowForcePushes *AllowForcePushes `json:"allow_force_pushes"` + AllowDeletions *AllowDeletions `json:"allow_deletions"` + RequiredConversationResolution *RequiredConversationResolution `json:"required_conversation_resolution"` +} + +// BranchProtectionRule represents the rule applied to a repositories branch. +type BranchProtectionRule struct { + ID *int64 `json:"id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + Name *string `json:"name,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + PullRequestReviewsEnforcementLevel *string `json:"pull_request_reviews_enforcement_level,omitempty"` + RequiredApprovingReviewCount *int `json:"required_approving_review_count,omitempty"` + DismissStaleReviewsOnPush *bool `json:"dismiss_stale_reviews_on_push,omitempty"` + AuthorizedDismissalActorsOnly *bool `json:"authorized_dismissal_actors_only,omitempty"` + IgnoreApprovalsFromContributors *bool `json:"ignore_approvals_from_contributors,omitempty"` + RequireCodeOwnerReview *bool `json:"require_code_owner_review,omitempty"` + RequiredStatusChecks []string `json:"required_status_checks,omitempty"` + RequiredStatusChecksEnforcementLevel *string `json:"required_status_checks_enforcement_level,omitempty"` + StrictRequiredStatusChecksPolicy *bool `json:"strict_required_status_checks_policy,omitempty"` + SignatureRequirementEnforcementLevel *string `json:"signature_requirement_enforcement_level,omitempty"` + LinearHistoryRequirementEnforcementLevel *string `json:"linear_history_requirement_enforcement_level,omitempty"` + AdminEnforced *bool `json:"admin_enforced,omitempty"` + AllowForcePushesEnforcementLevel *string `json:"allow_force_pushes_enforcement_level,omitempty"` + AllowDeletionsEnforcementLevel *string `json:"allow_deletions_enforcement_level,omitempty"` + MergeQueueEnforcementLevel *string `json:"merge_queue_enforcement_level,omitempty"` + RequiredDeploymentsEnforcementLevel *string `json:"required_deployments_enforcement_level,omitempty"` + RequiredConversationResolutionLevel *string `json:"required_conversation_resolution_level,omitempty"` + AuthorizedActorsOnly *bool `json:"authorized_actors_only,omitempty"` + AuthorizedActorNames []string `json:"authorized_actor_names,omitempty"` +} + +// ProtectionChanges represents the changes to the rule if the BranchProtection was edited. +type ProtectionChanges struct { + AuthorizedActorsOnly *AuthorizedActorsOnly `json:"authorized_actors_only,omitempty"` + AuthorizedActorNames *AuthorizedActorNames `json:"authorized_actor_names,omitempty"` +} + +// AuthorizedActorNames represents who are authorized to edit the branch protection rules. +type AuthorizedActorNames struct { + From []string `json:"from,omitempty"` +} + +// AuthorizedActorsOnly represents if the branche rule can be edited by authorized actors only. +type AuthorizedActorsOnly struct { + From *bool `json:"from,omitempty"` +} + +// ProtectionRequest represents a request to create/edit a branch's protection. +type ProtectionRequest struct { + RequiredStatusChecks *RequiredStatusChecks `json:"required_status_checks"` + RequiredPullRequestReviews *PullRequestReviewsEnforcementRequest `json:"required_pull_request_reviews"` + EnforceAdmins bool `json:"enforce_admins"` + Restrictions *BranchRestrictionsRequest `json:"restrictions"` + // Enforces a linear commit Git history, which prevents anyone from pushing merge commits to a branch. + RequireLinearHistory *bool `json:"required_linear_history,omitempty"` + // Permits force pushes to the protected branch by anyone with write access to the repository. + AllowForcePushes *bool `json:"allow_force_pushes,omitempty"` + // Allows deletion of the protected branch by anyone with write access to the repository. + AllowDeletions *bool `json:"allow_deletions,omitempty"` + // RequiredConversationResolution, if set to true, requires all comments + // on the pull request to be resolved before it can be merged to a protected branch. + RequiredConversationResolution *bool `json:"required_conversation_resolution,omitempty"` +} + +// RequiredStatusChecks represents the protection status of a individual branch. +type RequiredStatusChecks struct { + // Require branches to be up to date before merging. (Required.) + Strict bool `json:"strict"` + // The list of status checks to require in order to merge into this + // branch. (Deprecated. Note: only one of Contexts/Checks can be populated, + // but at least one must be populated). + Contexts []string `json:"contexts,omitempty"` + // The list of status checks to require in order to merge into this + // branch. + Checks []*RequiredStatusCheck `json:"checks,omitempty"` +} + +// RequiredStatusChecksRequest represents a request to edit a protected branch's status checks. +type RequiredStatusChecksRequest struct { + Strict *bool `json:"strict,omitempty"` + // Note: if both Contexts and Checks are populated, + // the GitHub API will only use Checks. + Contexts []string `json:"contexts,omitempty"` + Checks []*RequiredStatusCheck `json:"checks,omitempty"` +} + +// RequiredStatusCheck represents a status check of a protected branch. +type RequiredStatusCheck struct { + // The name of the required check. + Context string `json:"context"` + // The ID of the GitHub App that must provide this check. + // Omit this field to automatically select the GitHub App + // that has recently provided this check, + // or any app if it was not set by a GitHub App. + // Pass -1 to explicitly allow any app to set the status. + AppID *int64 `json:"app_id,omitempty"` +} + +// PullRequestReviewsEnforcement represents the pull request reviews enforcement of a protected branch. +type PullRequestReviewsEnforcement struct { + // Specifies which users and teams can dismiss pull request reviews. + DismissalRestrictions *DismissalRestrictions `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews are dismissed automatically, when a new commit is pushed. + DismissStaleReviews bool `json:"dismiss_stale_reviews"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1-6. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` +} + +// PullRequestReviewsEnforcementRequest represents request to set the pull request review +// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcement above +// because the request structure is different from the response structure. +type PullRequestReviewsEnforcementRequest struct { + // Specifies which users and teams should be allowed to dismiss pull request reviews. + // User and team dismissal restrictions are only available for + // organization-owned repositories. Must be nil for personal repositories. + DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. (Required) + DismissStaleReviews bool `json:"dismiss_stale_reviews"` + // RequireCodeOwnerReviews specifies if an approved review is required in pull requests including files with a designated code owner. + RequireCodeOwnerReviews bool `json:"require_code_owner_reviews"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1-6. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` +} + +// PullRequestReviewsEnforcementUpdate represents request to patch the pull request review +// enforcement of a protected branch. It is separate from PullRequestReviewsEnforcementRequest above +// because the patch request does not require all fields to be initialized. +type PullRequestReviewsEnforcementUpdate struct { + // Specifies which users and teams can dismiss pull request reviews. Can be omitted. + DismissalRestrictionsRequest *DismissalRestrictionsRequest `json:"dismissal_restrictions,omitempty"` + // Specifies if approved reviews can be dismissed automatically, when a new commit is pushed. Can be omitted. + DismissStaleReviews *bool `json:"dismiss_stale_reviews,omitempty"` + // RequireCodeOwnerReviews specifies if merging pull requests is blocked until code owners have reviewed. + RequireCodeOwnerReviews *bool `json:"require_code_owner_reviews,omitempty"` + // RequiredApprovingReviewCount specifies the number of approvals required before the pull request can be merged. + // Valid values are 1 - 6 or 0 to not require reviewers. + RequiredApprovingReviewCount int `json:"required_approving_review_count"` +} + +// RequireLinearHistory represents the configuration to enforce branches with no merge commit. +type RequireLinearHistory struct { + Enabled bool `json:"enabled"` +} + +// AllowDeletions represents the configuration to accept deletion of protected branches. +type AllowDeletions struct { + Enabled bool `json:"enabled"` +} + +// AllowForcePushes represents the configuration to accept forced pushes on protected branches. +type AllowForcePushes struct { + Enabled bool `json:"enabled"` +} + +// RequiredConversationResolution, if enabled, requires all comments on the pull request to be resolved before it can be merged to a protected branch. +type RequiredConversationResolution struct { + Enabled bool `json:"enabled"` +} + +// AdminEnforcement represents the configuration to enforce required status checks for repository administrators. +type AdminEnforcement struct { + URL *string `json:"url,omitempty"` + Enabled bool `json:"enabled"` +} + +// BranchRestrictions represents the restriction that only certain users or +// teams may push to a branch. +type BranchRestrictions struct { + // The list of user logins with push access. + Users []*User `json:"users"` + // The list of team slugs with push access. + Teams []*Team `json:"teams"` + // The list of app slugs with push access. + Apps []*App `json:"apps"` +} + +// BranchRestrictionsRequest represents the request to create/edit the +// restriction that only certain users or teams may push to a branch. It is +// separate from BranchRestrictions above because the request structure is +// different from the response structure. +type BranchRestrictionsRequest struct { + // The list of user logins with push access. (Required; use []string{} instead of nil for empty list.) + Users []string `json:"users"` + // The list of team slugs with push access. (Required; use []string{} instead of nil for empty list.) + Teams []string `json:"teams"` + // The list of app slugs with push access. + Apps []string `json:"apps,omitempty"` +} + +// DismissalRestrictions specifies which users and teams can dismiss pull request reviews. +type DismissalRestrictions struct { + // The list of users who can dimiss pull request reviews. + Users []*User `json:"users"` + // The list of teams which can dismiss pull request reviews. + Teams []*Team `json:"teams"` +} + +// DismissalRestrictionsRequest represents the request to create/edit the +// restriction to allows only specific users or teams to dimiss pull request reviews. It is +// separate from DismissalRestrictions above because the request structure is +// different from the response structure. +// Note: Both Users and Teams must be nil, or both must be non-nil. +type DismissalRestrictionsRequest struct { + // The list of user logins who can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Users *[]string `json:"users,omitempty"` + // The list of team slugs which can dismiss pull request reviews. (Required; use nil to disable dismissal_restrictions or &[]string{} otherwise.) + Teams *[]string `json:"teams,omitempty"` +} + +// SignaturesProtectedBranch represents the protection status of an individual branch. +type SignaturesProtectedBranch struct { + URL *string `json:"url,omitempty"` + // Commits pushed to matching branches must have verified signatures. + Enabled *bool `json:"enabled,omitempty"` +} + +// ListBranches lists branches for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branches#list-branches +func (s *RepositoriesService) ListBranches(ctx context.Context, owner string, repo string, opts *BranchListOptions) ([]*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var branches []*Branch + resp, err := s.client.Do(ctx, req, &branches) + if err != nil { + return nil, resp, err + } + + return branches, resp, nil +} + +// GetBranch gets the specified branch for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branches#get-a-branch +func (s *RepositoriesService) GetBranch(ctx context.Context, owner, repo, branch string, followRedirects bool) (*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v", owner, repo, branch) + + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, followRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + b := new(Branch) + err = json.NewDecoder(resp.Body).Decode(b) + return b, newResponse(resp), err +} + +// renameBranchRequest represents a request to rename a branch. +type renameBranchRequest struct { + NewName string `json:"new_name"` +} + +// RenameBranch renames a branch in a repository. +// +// To rename a non-default branch: Users must have push access. GitHub Apps must have the `contents:write` repository permission. +// To rename the default branch: Users must have admin or owner permissions. GitHub Apps must have the `administration:write` repository permission. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branches#rename-a-branch +func (s *RepositoriesService) RenameBranch(ctx context.Context, owner, repo, branch, newName string) (*Branch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/rename", owner, repo, branch) + r := &renameBranchRequest{NewName: newName} + req, err := s.client.NewRequest("POST", u, r) + if err != nil { + return nil, nil, err + } + + b := new(Branch) + resp, err := s.client.Do(ctx, req, b) + if err != nil { + return nil, resp, err + } + + return b, resp, nil +} + +// GetBranchProtection gets the protection of a given branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-branch-protection +func (s *RepositoriesService) GetBranchProtection(ctx context.Context, owner, repo, branch string) (*Protection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + p := new(Protection) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return p, resp, nil +} + +// GetRequiredStatusChecks gets the required status checks for a given protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-status-checks-protection +func (s *RepositoriesService) GetRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*RequiredStatusChecks, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + p := new(RequiredStatusChecks) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return p, resp, nil +} + +// ListRequiredStatusChecksContexts lists the required status checks contexts for a given protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-all-status-check-contexts +func (s *RepositoriesService) ListRequiredStatusChecksContexts(ctx context.Context, owner, repo, branch string) (contexts []string, resp *Response, err error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks/contexts", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + resp, err = s.client.Do(ctx, req, &contexts) + if err != nil { + if isBranchNotProtected(err) { + err = ErrBranchNotProtected + } + return nil, resp, err + } + + return contexts, resp, nil +} + +// UpdateBranchProtection updates the protection of a given branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-branch-protection +func (s *RepositoriesService) UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *ProtectionRequest) (*Protection, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) + req, err := s.client.NewRequest("PUT", u, preq) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + p := new(Protection) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// RemoveBranchProtection removes the protection of a given branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-branch-protection +func (s *RepositoriesService) RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetSignaturesProtectedBranch gets required signatures of protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-commit-signature-protection +func (s *RepositoriesService) GetSignaturesProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + p := new(SignaturesProtectedBranch) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} + +// RequireSignaturesOnProtectedBranch makes signed commits required on a protected branch. +// It requires admin access and branch protection to be enabled. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#create-commit-signature-protection +func (s *RepositoriesService) RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*SignaturesProtectedBranch, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + r := new(SignaturesProtectedBranch) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// OptionalSignaturesOnProtectedBranch removes required signed commits on a given branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-commit-signature-protection +func (s *RepositoriesService) OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_signatures", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeSignaturePreview) + + return s.client.Do(ctx, req, nil) +} + +// UpdateRequiredStatusChecks updates the required status checks for a given protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-status-check-protection +func (s *RepositoriesService) UpdateRequiredStatusChecks(ctx context.Context, owner, repo, branch string, sreq *RequiredStatusChecksRequest) (*RequiredStatusChecks, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) + req, err := s.client.NewRequest("PATCH", u, sreq) + if err != nil { + return nil, nil, err + } + + sc := new(RequiredStatusChecks) + resp, err := s.client.Do(ctx, req, sc) + if err != nil { + return nil, resp, err + } + + return sc, resp, nil +} + +// RemoveRequiredStatusChecks removes the required status checks for a given protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-status-check-protection +func (s *RepositoriesService) RemoveRequiredStatusChecks(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_status_checks", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// License gets the contents of a repository's license if one is detected. +// +// GitHub API docs: https://docs.github.com/en/rest/licenses#get-the-license-for-a-repository +func (s *RepositoriesService) License(ctx context.Context, owner, repo string) (*RepositoryLicense, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/license", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := &RepositoryLicense{} + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// GetPullRequestReviewEnforcement gets pull request review enforcement of a protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-pull-request-review-protection +func (s *RepositoriesService) GetPullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// UpdatePullRequestReviewEnforcement patches pull request review enforcement of a protected branch. +// It requires admin access and branch protection to be enabled. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-pull-request-review-protection +func (s *RepositoriesService) UpdatePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string, patch *PullRequestReviewsEnforcementUpdate) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) + req, err := s.client.NewRequest("PATCH", u, patch) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DisableDismissalRestrictions disables dismissal restrictions of a protected branch. +// It requires admin access and branch protection to be enabled. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#update-pull-request-review-protection +func (s *RepositoriesService) DisableDismissalRestrictions(ctx context.Context, owner, repo, branch string) (*PullRequestReviewsEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) + + data := new(struct { + DismissalRestrictionsRequest `json:"dismissal_restrictions"` + }) + + req, err := s.client.NewRequest("PATCH", u, data) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches + req.Header.Set("Accept", mediaTypeRequiredApprovingReviewsPreview) + + r := new(PullRequestReviewsEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemovePullRequestReviewEnforcement removes pull request enforcement of a protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-pull-request-review-protection +func (s *RepositoriesService) RemovePullRequestReviewEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/required_pull_request_reviews", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// GetAdminEnforcement gets admin enforcement information of a protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-admin-branch-protection +func (s *RepositoriesService) GetAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(AdminEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// AddAdminEnforcement adds admin enforcement to a protected branch. +// It requires admin access and branch protection to be enabled. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-admin-branch-protection +func (s *RepositoriesService) AddAdminEnforcement(ctx context.Context, owner, repo, branch string) (*AdminEnforcement, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + r := new(AdminEnforcement) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// RemoveAdminEnforcement removes admin enforcement from a protected branch. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#delete-admin-branch-protection +func (s *RepositoriesService) RemoveAdminEnforcement(ctx context.Context, owner, repo, branch string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/enforce_admins", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// repositoryTopics represents a collection of repository topics. +type repositoryTopics struct { + Names []string `json:"names"` +} + +// ListAllTopics lists topics for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#get-all-repository-topics +func (s *RepositoriesService) ListAllTopics(ctx context.Context, owner, repo string) ([]string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + topics := new(repositoryTopics) + resp, err := s.client.Do(ctx, req, topics) + if err != nil { + return nil, resp, err + } + + return topics.Names, resp, nil +} + +// ReplaceAllTopics replaces all repository topics. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#replace-all-repository-topics +func (s *RepositoriesService) ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/topics", owner, repo) + t := &repositoryTopics{ + Names: topics, + } + if t.Names == nil { + t.Names = []string{} + } + req, err := s.client.NewRequest("PUT", u, t) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + t = new(repositoryTopics) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t.Names, resp, nil +} + +// ListApps lists the GitHub apps that have push access to a given protected branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#get-apps-with-access-to-the-protected-branch +func (s *RepositoriesService) ListApps(ctx context.Context, owner, repo, branch string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var apps []*App + resp, err := s.client.Do(ctx, req, &apps) + if err != nil { + return nil, resp, err + } + + return apps, resp, nil +} + +// ReplaceAppRestrictions replaces the apps that have push access to a given protected branch. +// It removes all apps that previously had push access and grants push access to the new list of apps. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#set-app-access-restrictions +func (s *RepositoriesService) ReplaceAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch) + req, err := s.client.NewRequest("PUT", u, slug) + if err != nil { + return nil, nil, err + } + + var apps []*App + resp, err := s.client.Do(ctx, req, &apps) + if err != nil { + return nil, resp, err + } + + return apps, resp, nil +} + +// AddAppRestrictions grants the specified apps push access to a given protected branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#add-app-access-restrictions +func (s *RepositoriesService) AddAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch) + req, err := s.client.NewRequest("POST", u, slug) + if err != nil { + return nil, nil, err + } + + var apps []*App + resp, err := s.client.Do(ctx, req, &apps) + if err != nil { + return nil, resp, err + } + + return apps, resp, nil +} + +// RemoveAppRestrictions removes the ability of an app to push to this branch. +// It requires the GitHub apps to have `write` access to the `content` permission. +// +// Note: The list of users, apps, and teams in total is limited to 100 items. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branch-protection#remove-app-access-restrictions +func (s *RepositoriesService) RemoveAppRestrictions(ctx context.Context, owner, repo, branch string, slug []string) ([]*App, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/branches/%v/protection/restrictions/apps", owner, repo, branch) + req, err := s.client.NewRequest("DELETE", u, slug) + if err != nil { + return nil, nil, err + } + + var apps []*App + resp, err := s.client.Do(ctx, req, &apps) + if err != nil { + return nil, resp, err + } + + return apps, resp, nil +} + +// TransferRequest represents a request to transfer a repository. +type TransferRequest struct { + NewOwner string `json:"new_owner"` + TeamID []int64 `json:"team_ids,omitempty"` +} + +// Transfer transfers a repository from one account or organization to another. +// +// This method might return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it has now scheduled the transfer of the repository in a background task. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#transfer-a-repository +func (s *RepositoriesService) Transfer(ctx context.Context, owner, repo string, transfer TransferRequest) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/transfer", owner, repo) + + req, err := s.client.NewRequest("POST", u, &transfer) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// DispatchRequestOptions represents a request to trigger a repository_dispatch event. +type DispatchRequestOptions struct { + // EventType is a custom webhook event name. (Required.) + EventType string `json:"event_type"` + // ClientPayload is a custom JSON payload with extra information about the webhook event. + // Defaults to an empty JSON object. + ClientPayload *json.RawMessage `json:"client_payload,omitempty"` +} + +// Dispatch triggers a repository_dispatch event in a GitHub Actions workflow. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/repos#create-a-repository-dispatch-event +func (s *RepositoriesService) Dispatch(ctx context.Context, owner, repo string, opts DispatchRequestOptions) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/dispatches", owner, repo) + + req, err := s.client.NewRequest("POST", u, &opts) + if err != nil { + return nil, nil, err + } + + r := new(Repository) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +// isBranchNotProtected determines whether a branch is not protected +// based on the error message returned by GitHub API. +func isBranchNotProtected(err error) bool { + errorResponse, ok := err.(*ErrorResponse) + return ok && errorResponse.Message == githubBranchNotProtected +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_actions_allowed.go b/vendor/github.com/google/go-github/v45/github/repos_actions_allowed.go new file mode 100644 index 0000000000..25a4690583 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_actions_allowed.go @@ -0,0 +1,49 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// GetActionsAllowed gets the allowed actions and reusable workflows for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#get-allowed-actions-and-reusable-workflows-for-a-repository +func (s *RepositoriesService) GetActionsAllowed(ctx context.Context, org, repo string) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/selected-actions", org, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + actionsAllowed := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, actionsAllowed) + if err != nil { + return nil, resp, err + } + + return actionsAllowed, resp, nil +} + +// EditActionsAllowed sets the allowed actions and reusable workflows for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#set-allowed-actions-and-reusable-workflows-for-a-repository +func (s *RepositoriesService) EditActionsAllowed(ctx context.Context, org, repo string, actionsAllowed ActionsAllowed) (*ActionsAllowed, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions/selected-actions", org, repo) + req, err := s.client.NewRequest("PUT", u, actionsAllowed) + if err != nil { + return nil, nil, err + } + + p := new(ActionsAllowed) + resp, err := s.client.Do(ctx, req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_actions_permissions.go b/vendor/github.com/google/go-github/v45/github/repos_actions_permissions.go new file mode 100644 index 0000000000..45f844cec0 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_actions_permissions.go @@ -0,0 +1,62 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ActionsPermissionsRepository represents a policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions +type ActionsPermissionsRepository struct { + Enabled *bool `json:"enabled,omitempty"` + AllowedActions *string `json:"allowed_actions,omitempty"` + SelectedActionsURL *string `json:"selected_actions_url,omitempty"` +} + +func (a ActionsPermissionsRepository) String() string { + return Stringify(a) +} + +// GetActionsPermissions gets the GitHub Actions permissions policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#get-github-actions-permissions-for-a-repository +func (s *RepositoriesService) GetActionsPermissions(ctx context.Context, owner, repo string) (*ActionsPermissionsRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissionsRepository) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} + +// EditActionsPermissions sets the permissions policy for repositories and allowed actions in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/actions/permissions#set-github-actions-permissions-for-a-repository +func (s *RepositoriesService) EditActionsPermissions(ctx context.Context, owner, repo string, actionsPermissionsRepository ActionsPermissionsRepository) (*ActionsPermissionsRepository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/actions/permissions", owner, repo) + req, err := s.client.NewRequest("PUT", u, actionsPermissionsRepository) + if err != nil { + return nil, nil, err + } + + permissions := new(ActionsPermissionsRepository) + resp, err := s.client.Do(ctx, req, permissions) + if err != nil { + return nil, resp, err + } + + return permissions, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_autolinks.go b/vendor/github.com/google/go-github/v45/github/repos_autolinks.go new file mode 100644 index 0000000000..8fa916eac2 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_autolinks.go @@ -0,0 +1,102 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// AutolinkOptions specifies parameters for RepositoriesService.AddAutolink method. +type AutolinkOptions struct { + KeyPrefix *string `json:"key_prefix,omitempty"` + URLTemplate *string `json:"url_template,omitempty"` +} + +// Autolink represents autolinks to external resources like JIRA issues and Zendesk tickets. +type Autolink struct { + ID *int64 `json:"id,omitempty"` + KeyPrefix *string `json:"key_prefix,omitempty"` + URLTemplate *string `json:"url_template,omitempty"` +} + +// ListAutolinks returns a list of autolinks configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/autolinks#list-all-autolinks-of-a-repository +func (s *RepositoriesService) ListAutolinks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var autolinks []*Autolink + resp, err := s.client.Do(ctx, req, &autolinks) + if err != nil { + return nil, resp, err + } + + return autolinks, resp, nil +} + +// AddAutolink creates an autolink reference for a repository. +// Users with admin access to the repository can create an autolink. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/autolinks#create-an-autolink-reference-for-a-repository +func (s *RepositoriesService) AddAutolink(ctx context.Context, owner, repo string, opts *AutolinkOptions) (*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + al := new(Autolink) + resp, err := s.client.Do(ctx, req, al) + if err != nil { + return nil, resp, err + } + return al, resp, nil +} + +// GetAutolink returns a single autolink reference by ID that was configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/autolinks#get-an-autolink-reference-of-a-repository +func (s *RepositoriesService) GetAutolink(ctx context.Context, owner, repo string, id int64) (*Autolink, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var autolink *Autolink + resp, err := s.client.Do(ctx, req, &autolink) + if err != nil { + return nil, resp, err + } + + return autolink, resp, nil +} + +// DeleteAutolink deletes a single autolink reference by ID that was configured for the given repository. +// Information about autolinks are only available to repository administrators. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/autolinks#delete-an-autolink-reference-from-a-repository +func (s *RepositoriesService) DeleteAutolink(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/autolinks/%v", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_collaborators.go b/vendor/github.com/google/go-github/v45/github/repos_collaborators.go new file mode 100644 index 0000000000..abc4161c3b --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_collaborators.go @@ -0,0 +1,159 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListCollaboratorsOptions specifies the optional parameters to the +// RepositoriesService.ListCollaborators method. +type ListCollaboratorsOptions struct { + // Affiliation specifies how collaborators should be filtered by their affiliation. + // Possible values are: + // outside - All outside collaborators of an organization-owned repository + // direct - All collaborators with permissions to an organization-owned repository, + // regardless of organization membership status + // all - All collaborators the authenticated user can see + // + // Default value is "all". + Affiliation string `url:"affiliation,omitempty"` + + ListOptions +} + +// CollaboratorInvitation represents an invitation created when adding a collaborator. +// GitHub API docs: https://docs.github.com/en/rest/repos/collaborators/#response-when-a-new-invitation-is-created +type CollaboratorInvitation struct { + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Invitee *User `json:"invitee,omitempty"` + Inviter *User `json:"inviter,omitempty"` + Permissions *string `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// ListCollaborators lists the GitHub users that have access to the repository. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/collaborators#list-repository-collaborators +func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opts *ListCollaboratorsOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// IsCollaborator checks whether the specified GitHub user has collaborator +// access to the given repo. +// Note: This will return false if the user is not a collaborator OR the user +// is not a GitHub user. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/collaborators#check-if-a-user-is-a-repository-collaborator +func (s *RepositoriesService) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + isCollab, err := parseBoolResponse(err) + return isCollab, resp, err +} + +// RepositoryPermissionLevel represents the permission level an organization +// member has for a given repository. +type RepositoryPermissionLevel struct { + // Possible values: "admin", "write", "read", "none" + Permission *string `json:"permission,omitempty"` + + User *User `json:"user,omitempty"` +} + +// GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/collaborators#get-repository-permissions-for-a-user +func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + rpl := new(RepositoryPermissionLevel) + resp, err := s.client.Do(ctx, req, rpl) + if err != nil { + return nil, resp, err + } + + return rpl, resp, nil +} + +// RepositoryAddCollaboratorOptions specifies the optional parameters to the +// RepositoriesService.AddCollaborator method. +type RepositoryAddCollaboratorOptions struct { + // Permission specifies the permission to grant the user on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // maintain - team members can manage the repository without access to sensitive or destructive actions. + // triage - team members can proactively manage issues and pull requests without write access. + // + // Default value is "push". This option is only valid for organization-owned repositories. + Permission string `json:"permission,omitempty"` +} + +// AddCollaborator sends an invitation to the specified GitHub user +// to become a collaborator to the given repo. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/collaborators#add-a-repository-collaborator +func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opts *RepositoryAddCollaboratorOptions) (*CollaboratorInvitation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + acr := new(CollaboratorInvitation) + resp, err := s.client.Do(ctx, req, acr) + if err != nil { + return nil, resp, err + } + + return acr, resp, nil +} + +// RemoveCollaborator removes the specified GitHub user as collaborator from the given repo. +// Note: Does not return error if a valid user that is not a collaborator is removed. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/collaborators#remove-a-repository-collaborator +func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_comments.go b/vendor/github.com/google/go-github/v45/github/repos_comments.go new file mode 100644 index 0000000000..55a88d1f5e --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_comments.go @@ -0,0 +1,162 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// RepositoryComment represents a comment for a commit, file, or line in a repository. +type RepositoryComment struct { + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + CommitID *string `json:"commit_id,omitempty"` + User *User `json:"user,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + + // User-mutable fields + Body *string `json:"body"` + // User-initialized fields + Path *string `json:"path,omitempty"` + Position *int `json:"position,omitempty"` +} + +func (r RepositoryComment) String() string { + return Stringify(r) +} + +// ListComments lists all the comments for the repository. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/comments#list-commit-comments-for-a-repository +func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*RepositoryComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// ListCommitComments lists all the comments for a given commit SHA. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/comments#list-commit-comments +func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opts *ListOptions) ([]*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + var comments []*RepositoryComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// CreateComment creates a comment for the given commit. +// Note: GitHub allows for comments to be created for non-existing files and positions. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/comments#create-a-commit-comment +func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sha string, comment *RepositoryComment) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// GetComment gets a single comment from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/comments#get-a-commit-comment +func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// UpdateComment updates the body of a single comment. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/comments#update-a-commit-comment +func (s *RepositoriesService) UpdateComment(ctx context.Context, owner, repo string, id int64, comment *RepositoryComment) (*RepositoryComment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + c := new(RepositoryComment) + resp, err := s.client.Do(ctx, req, c) + if err != nil { + return nil, resp, err + } + + return c, resp, nil +} + +// DeleteComment deletes a single comment from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/comments#delete-a-commit-comment +func (s *RepositoriesService) DeleteComment(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_commits.go b/vendor/github.com/google/go-github/v45/github/repos_commits.go new file mode 100644 index 0000000000..d1fb577c61 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_commits.go @@ -0,0 +1,312 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "context" + "fmt" + "net/url" + "time" +) + +// RepositoryCommit represents a commit in a repo. +// Note that it's wrapping a Commit, so author/committer information is in two places, +// but contain different details about them: in RepositoryCommit "github details", in Commit - "git details". +type RepositoryCommit struct { + NodeID *string `json:"node_id,omitempty"` + SHA *string `json:"sha,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Author *User `json:"author,omitempty"` + Committer *User `json:"committer,omitempty"` + Parents []*Commit `json:"parents,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + + // Details about how many changes were made in this commit. Only filled in during GetCommit! + Stats *CommitStats `json:"stats,omitempty"` + // Details about which files, and how this commit touched. Only filled in during GetCommit! + Files []*CommitFile `json:"files,omitempty"` +} + +func (r RepositoryCommit) String() string { + return Stringify(r) +} + +// CommitStats represents the number of additions / deletions from a file in a given RepositoryCommit or GistCommit. +type CommitStats struct { + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + Total *int `json:"total,omitempty"` +} + +func (c CommitStats) String() string { + return Stringify(c) +} + +// CommitFile represents a file modified in a commit. +type CommitFile struct { + SHA *string `json:"sha,omitempty"` + Filename *string `json:"filename,omitempty"` + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + Changes *int `json:"changes,omitempty"` + Status *string `json:"status,omitempty"` + Patch *string `json:"patch,omitempty"` + BlobURL *string `json:"blob_url,omitempty"` + RawURL *string `json:"raw_url,omitempty"` + ContentsURL *string `json:"contents_url,omitempty"` + PreviousFilename *string `json:"previous_filename,omitempty"` +} + +func (c CommitFile) String() string { + return Stringify(c) +} + +// CommitsComparison is the result of comparing two commits. +// See CompareCommits() for details. +type CommitsComparison struct { + BaseCommit *RepositoryCommit `json:"base_commit,omitempty"` + MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"` + + // Head can be 'behind' or 'ahead' + Status *string `json:"status,omitempty"` + AheadBy *int `json:"ahead_by,omitempty"` + BehindBy *int `json:"behind_by,omitempty"` + TotalCommits *int `json:"total_commits,omitempty"` + + Commits []*RepositoryCommit `json:"commits,omitempty"` + + Files []*CommitFile `json:"files,omitempty"` + + HTMLURL *string `json:"html_url,omitempty"` + PermalinkURL *string `json:"permalink_url,omitempty"` + DiffURL *string `json:"diff_url,omitempty"` + PatchURL *string `json:"patch_url,omitempty"` + URL *string `json:"url,omitempty"` // API URL. +} + +func (c CommitsComparison) String() string { + return Stringify(c) +} + +// CommitsListOptions specifies the optional parameters to the +// RepositoriesService.ListCommits method. +type CommitsListOptions struct { + // SHA or branch to start listing Commits from. + SHA string `url:"sha,omitempty"` + + // Path that should be touched by the returned Commits. + Path string `url:"path,omitempty"` + + // Author of by which to filter Commits. + Author string `url:"author,omitempty"` + + // Since when should Commits be included in the response. + Since time.Time `url:"since,omitempty"` + + // Until when should Commits be included in the response. + Until time.Time `url:"until,omitempty"` + + ListOptions +} + +// BranchCommit is the result of listing branches with commit SHA. +type BranchCommit struct { + Name *string `json:"name,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Protected *bool `json:"protected,omitempty"` +} + +// ListCommits lists the commits of a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#list-commits +func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opts *CommitsListOptions) ([]*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var commits []*RepositoryCommit + resp, err := s.client.Do(ctx, req, &commits) + if err != nil { + return nil, resp, err + } + + return commits, resp, nil +} + +// GetCommit fetches the specified commit, including all details about it. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#get-a-single-commit +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#get-a-commit +func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string, opts *ListOptions) (*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + commit := new(RepositoryCommit) + resp, err := s.client.Do(ctx, req, commit) + if err != nil { + return nil, resp, err + } + + return commit, resp, nil +} + +// GetCommitRaw fetches the specified commit in raw (diff or patch) format. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#get-a-commit +func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opts RawOptions) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opts.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is +// supplied and no new commits have occurred, a 304 Unmodified response is returned. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#get-a-commit +func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, refURLEscape(ref)) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + if lastSHA != "" { + req.Header.Set("If-None-Match", `"`+lastSHA+`"`) + } + + req.Header.Set("Accept", mediaTypeV3SHA) + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// CompareCommits compares a range of commits with each other. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#compare-two-commits +func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string, opts *ListOptions) (*CommitsComparison, *Response, error) { + escapedBase := url.QueryEscape(base) + escapedHead := url.QueryEscape(head) + + u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, escapedBase, escapedHead) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + comp := new(CommitsComparison) + resp, err := s.client.Do(ctx, req, comp) + if err != nil { + return nil, resp, err + } + + return comp, resp, nil +} + +// CompareCommitsRaw compares a range of commits with each other in raw (diff or patch) format. +// +// Both "base" and "head" must be branch names in "repo". +// To compare branches across other repositories in the same network as "repo", +// use the format ":branch". +// +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#compare-two-commits +func (s *RepositoriesService) CompareCommitsRaw(ctx context.Context, owner, repo, base, head string, opts RawOptions) (string, *Response, error) { + escapedBase := url.QueryEscape(base) + escapedHead := url.QueryEscape(head) + + u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, escapedBase, escapedHead) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return "", nil, err + } + + switch opts.Type { + case Diff: + req.Header.Set("Accept", mediaTypeV3Diff) + case Patch: + req.Header.Set("Accept", mediaTypeV3Patch) + default: + return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type) + } + + var buf bytes.Buffer + resp, err := s.client.Do(ctx, req, &buf) + if err != nil { + return "", resp, err + } + + return buf.String(), resp, nil +} + +// ListBranchesHeadCommit gets all branches where the given commit SHA is the HEAD, +// or latest commit for the branch. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/commits#list-branches-for-head-commit +func (s *RepositoriesService) ListBranchesHeadCommit(ctx context.Context, owner, repo, sha string) ([]*BranchCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/branches-where-head", owner, repo, sha) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview) + var branchCommits []*BranchCommit + resp, err := s.client.Do(ctx, req, &branchCommits) + if err != nil { + return nil, resp, err + } + + return branchCommits, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_community_health.go b/vendor/github.com/google/go-github/v45/github/repos_community_health.go new file mode 100644 index 0000000000..9de438b625 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_community_health.go @@ -0,0 +1,62 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// Metric represents the different fields for one file in community health files. +type Metric struct { + Name *string `json:"name"` + Key *string `json:"key"` + SPDXID *string `json:"spdx_id"` + URL *string `json:"url"` + HTMLURL *string `json:"html_url"` + NodeID *string `json:"node_id"` +} + +// CommunityHealthFiles represents the different files in the community health metrics response. +type CommunityHealthFiles struct { + CodeOfConduct *Metric `json:"code_of_conduct"` + CodeOfConductFile *Metric `json:"code_of_conduct_file"` + Contributing *Metric `json:"contributing"` + IssueTemplate *Metric `json:"issue_template"` + PullRequestTemplate *Metric `json:"pull_request_template"` + License *Metric `json:"license"` + Readme *Metric `json:"readme"` +} + +// CommunityHealthMetrics represents a response containing the community metrics of a repository. +type CommunityHealthMetrics struct { + HealthPercentage *int `json:"health_percentage"` + Description *string `json:"description"` + Documentation *string `json:"documentation"` + Files *CommunityHealthFiles `json:"files"` + UpdatedAt *time.Time `json:"updated_at"` + ContentReportsEnabled *bool `json:"content_reports_enabled"` +} + +// GetCommunityHealthMetrics retrieves all the community health metrics for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/community#get-community-profile-metrics +func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + metrics := &CommunityHealthMetrics{} + resp, err := s.client.Do(ctx, req, metrics) + if err != nil { + return nil, resp, err + } + + return metrics, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_contents.go b/vendor/github.com/google/go-github/v45/github/repos_contents.go new file mode 100644 index 0000000000..d6f2dd9d74 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_contents.go @@ -0,0 +1,321 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Repository contents API methods. +// GitHub API docs: https://docs.github.com/en/rest/repos/contents/ + +package github + +import ( + "context" + "encoding/base64" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" +) + +// RepositoryContent represents a file or directory in a github repository. +type RepositoryContent struct { + Type *string `json:"type,omitempty"` + // Target is only set if the type is "symlink" and the target is not a normal file. + // If Target is set, Path will be the symlink path. + Target *string `json:"target,omitempty"` + Encoding *string `json:"encoding,omitempty"` + Size *int `json:"size,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + // Content contains the actual file content, which may be encoded. + // Callers should call GetContent which will decode the content if + // necessary. + Content *string `json:"content,omitempty"` + SHA *string `json:"sha,omitempty"` + URL *string `json:"url,omitempty"` + GitURL *string `json:"git_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + DownloadURL *string `json:"download_url,omitempty"` +} + +// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile. +type RepositoryContentResponse struct { + Content *RepositoryContent `json:"content,omitempty"` + Commit `json:"commit,omitempty"` +} + +// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile. +type RepositoryContentFileOptions struct { + Message *string `json:"message,omitempty"` + Content []byte `json:"content,omitempty"` // unencoded + SHA *string `json:"sha,omitempty"` + Branch *string `json:"branch,omitempty"` + Author *CommitAuthor `json:"author,omitempty"` + Committer *CommitAuthor `json:"committer,omitempty"` +} + +// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA, +// branch, or tag +type RepositoryContentGetOptions struct { + Ref string `url:"ref,omitempty"` +} + +// String converts RepositoryContent to a string. It's primarily for testing. +func (r RepositoryContent) String() string { + return Stringify(r) +} + +// GetContent returns the content of r, decoding it if necessary. +func (r *RepositoryContent) GetContent() (string, error) { + var encoding string + if r.Encoding != nil { + encoding = *r.Encoding + } + + switch encoding { + case "base64": + if r.Content == nil { + return "", errors.New("malformed response: base64 encoding of null content") + } + c, err := base64.StdEncoding.DecodeString(*r.Content) + return string(c), err + case "": + if r.Content == nil { + return "", nil + } + return *r.Content, nil + default: + return "", fmt.Errorf("unsupported content encoding: %v", encoding) + } +} + +// GetReadme gets the Readme file for the repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/contents#get-a-repository-readme +func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opts *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/readme", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + readme := new(RepositoryContent) + resp, err := s.client.Do(ctx, req, readme) + if err != nil { + return nil, resp, err + } + + return readme, resp, nil +} + +// DownloadContents returns an io.ReadCloser that reads the contents of the +// specified file. This function will work with files of any size, as opposed +// to GetContents which is limited to 1 Mb files. It is the caller's +// responsibility to close the ReadCloser. +// +// It is possible for the download to result in a failed response when the +// returned error is nil. Callers should check the returned Response status +// code to verify the content is from a successful response. +func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, *Response, error) { + dir := path.Dir(filepath) + filename := path.Base(filepath) + _, dirContents, resp, err := s.GetContents(ctx, owner, repo, dir, opts) + if err != nil { + return nil, resp, err + } + + for _, contents := range dirContents { + if *contents.Name == filename { + if contents.DownloadURL == nil || *contents.DownloadURL == "" { + return nil, resp, fmt.Errorf("no download link found for %s", filepath) + } + + dlResp, err := s.client.client.Get(*contents.DownloadURL) + if err != nil { + return nil, &Response{Response: dlResp}, err + } + + return dlResp.Body, &Response{Response: dlResp}, nil + } + } + + return nil, resp, fmt.Errorf("no file named %s found in %s", filename, dir) +} + +// DownloadContentsWithMeta is identical to DownloadContents but additionally +// returns the RepositoryContent of the requested file. This additional data +// is useful for future operations involving the requested file. For merely +// reading the content of a file, DownloadContents is perfectly adequate. +// +// It is possible for the download to result in a failed response when the +// returned error is nil. Callers should check the returned Response status +// code to verify the content is from a successful response. +func (s *RepositoriesService) DownloadContentsWithMeta(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, *RepositoryContent, *Response, error) { + dir := path.Dir(filepath) + filename := path.Base(filepath) + _, dirContents, resp, err := s.GetContents(ctx, owner, repo, dir, opts) + if err != nil { + return nil, nil, resp, err + } + + for _, contents := range dirContents { + if *contents.Name == filename { + if contents.DownloadURL == nil || *contents.DownloadURL == "" { + return nil, contents, resp, fmt.Errorf("no download link found for %s", filepath) + } + + dlResp, err := s.client.client.Get(*contents.DownloadURL) + if err != nil { + return nil, contents, &Response{Response: dlResp}, err + } + + return dlResp.Body, contents, &Response{Response: dlResp}, nil + } + } + + return nil, nil, resp, fmt.Errorf("no file named %s found in %s", filename, dir) +} + +// GetContents can return either the metadata and content of a single file +// (when path references a file) or the metadata of all the files and/or +// subdirectories of a directory (when path references a directory). To make it +// easy to distinguish between both result types and to mimic the API as much +// as possible, both result types will be returned but only one will contain a +// value and the other will be nil. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/contents#get-repository-content +func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opts *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) { + escapedPath := (&url.URL{Path: strings.TrimSuffix(path, "/")}).String() + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath) + u, err = addOptions(u, opts) + if err != nil { + return nil, nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, nil, err + } + + var rawJSON json.RawMessage + resp, err = s.client.Do(ctx, req, &rawJSON) + if err != nil { + return nil, nil, resp, err + } + + fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent) + if fileUnmarshalError == nil { + return fileContent, nil, resp, nil + } + + directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent) + if directoryUnmarshalError == nil { + return nil, directoryContent, resp, nil + } + + return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError) +} + +// CreateFile creates a new file in a repository at the given path and returns +// the commit and file metadata. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/contents#create-or-update-file-contents +func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + createResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, createResponse) + if err != nil { + return nil, resp, err + } + + return createResponse, resp, nil +} + +// UpdateFile updates a file in a repository at the given path and returns the +// commit and file metadata. Requires the blob SHA of the file being updated. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/contents#create-or-update-file-contents +func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + updateResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, updateResponse) + if err != nil { + return nil, resp, err + } + + return updateResponse, resp, nil +} + +// DeleteFile deletes a file from a repository and returns the commit. +// Requires the blob SHA of the file to be deleted. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/contents#delete-a-file +func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path) + req, err := s.client.NewRequest("DELETE", u, opts) + if err != nil { + return nil, nil, err + } + + deleteResponse := new(RepositoryContentResponse) + resp, err := s.client.Do(ctx, req, deleteResponse) + if err != nil { + return nil, resp, err + } + + return deleteResponse, resp, nil +} + +// ArchiveFormat is used to define the archive type when calling GetArchiveLink. +type ArchiveFormat string + +const ( + // Tarball specifies an archive in gzipped tar format. + Tarball ArchiveFormat = "tarball" + + // Zipball specifies an archive in zip format. + Zipball ArchiveFormat = "zipball" +) + +// GetArchiveLink returns an URL to download a tarball or zipball archive for a +// repository. The archiveFormat can be specified by either the github.Tarball +// or github.Zipball constant. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/contents/#get-archive-link +func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat ArchiveFormat, opts *RepositoryContentGetOptions, followRedirects bool) (*url.URL, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat) + if opts != nil && opts.Ref != "" { + u += fmt.Sprintf("/%s", opts.Ref) + } + resp, err := s.client.roundTripWithOptionalFollowRedirect(ctx, u, followRedirects) + if err != nil { + return nil, nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status) + } + + parsedURL, err := url.Parse(resp.Header.Get("Location")) + return parsedURL, newResponse(resp), err +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_deployments.go b/vendor/github.com/google/go-github/v45/github/repos_deployments.go new file mode 100644 index 0000000000..36445f895e --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_deployments.go @@ -0,0 +1,250 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" + "strings" +) + +// Deployment represents a deployment in a repo +type Deployment struct { + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + SHA *string `json:"sha,omitempty"` + Ref *string `json:"ref,omitempty"` + Task *string `json:"task,omitempty"` + Payload json.RawMessage `json:"payload,omitempty"` + Environment *string `json:"environment,omitempty"` + Description *string `json:"description,omitempty"` + Creator *User `json:"creator,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + StatusesURL *string `json:"statuses_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +// DeploymentRequest represents a deployment request +type DeploymentRequest struct { + Ref *string `json:"ref,omitempty"` + Task *string `json:"task,omitempty"` + AutoMerge *bool `json:"auto_merge,omitempty"` + RequiredContexts *[]string `json:"required_contexts,omitempty"` + Payload interface{} `json:"payload,omitempty"` + Environment *string `json:"environment,omitempty"` + Description *string `json:"description,omitempty"` + TransientEnvironment *bool `json:"transient_environment,omitempty"` + ProductionEnvironment *bool `json:"production_environment,omitempty"` +} + +// DeploymentsListOptions specifies the optional parameters to the +// RepositoriesService.ListDeployments method. +type DeploymentsListOptions struct { + // SHA of the Deployment. + SHA string `url:"sha,omitempty"` + + // List deployments for a given ref. + Ref string `url:"ref,omitempty"` + + // List deployments for a given task. + Task string `url:"task,omitempty"` + + // List deployments for a given environment. + Environment string `url:"environment,omitempty"` + + ListOptions +} + +// ListDeployments lists the deployments of a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/deployments#list-deployments +func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opts *DeploymentsListOptions) ([]*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var deployments []*Deployment + resp, err := s.client.Do(ctx, req, &deployments) + if err != nil { + return nil, resp, err + } + + return deployments, resp, nil +} + +// GetDeployment returns a single deployment of a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/deployments#get-a-deployment +func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deployment := new(Deployment) + resp, err := s.client.Do(ctx, req, deployment) + if err != nil { + return nil, resp, err + } + + return deployment, resp, nil +} + +// CreateDeployment creates a new deployment for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/deployments#create-a-deployment +func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo string, request *DeploymentRequest) (*Deployment, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(Deployment) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} + +// DeleteDeployment deletes an existing deployment for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/deployments#delete-a-deployment +func (s *RepositoriesService) DeleteDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// DeploymentStatus represents the status of a +// particular deployment. +type DeploymentStatus struct { + ID *int64 `json:"id,omitempty"` + // State is the deployment state. + // Possible values are: "pending", "success", "failure", "error", + // "inactive", "in_progress", "queued". + State *string `json:"state,omitempty"` + Creator *User `json:"creator,omitempty"` + Description *string `json:"description,omitempty"` + Environment *string `json:"environment,omitempty"` + NodeID *string `json:"node_id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + TargetURL *string `json:"target_url,omitempty"` + DeploymentURL *string `json:"deployment_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` + EnvironmentURL *string `json:"environment_url,omitempty"` + LogURL *string `json:"log_url,omitempty"` + URL *string `json:"url,omitempty"` +} + +// DeploymentStatusRequest represents a deployment request +type DeploymentStatusRequest struct { + State *string `json:"state,omitempty"` + LogURL *string `json:"log_url,omitempty"` + Description *string `json:"description,omitempty"` + Environment *string `json:"environment,omitempty"` + EnvironmentURL *string `json:"environment_url,omitempty"` + AutoInactive *bool `json:"auto_inactive,omitempty"` +} + +// ListDeploymentStatuses lists the statuses of a given deployment of a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/statuses#list-deployment-statuses +func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opts *ListOptions) ([]*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var statuses []*DeploymentStatus + resp, err := s.client.Do(ctx, req, &statuses) + if err != nil { + return nil, resp, err + } + + return statuses, resp, nil +} + +// GetDeploymentStatus returns a single deployment status of a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/statuses#get-a-deployment-status +func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(DeploymentStatus) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} + +// CreateDeploymentStatus creates a new status for a deployment. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/statuses#create-a-deployment-status +func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, repo string, deployment int64, request *DeploymentStatusRequest) (*DeploymentStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment) + + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + d := new(DeploymentStatus) + resp, err := s.client.Do(ctx, req, d) + if err != nil { + return nil, resp, err + } + + return d, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_environments.go b/vendor/github.com/google/go-github/v45/github/repos_environments.go new file mode 100644 index 0000000000..365f8d9202 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_environments.go @@ -0,0 +1,201 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// Environment represents a single environment in a repository. +type Environment struct { + Owner *string `json:"owner,omitempty"` + Repo *string `json:"repo,omitempty"` + EnvironmentName *string `json:"environment_name,omitempty"` + WaitTimer *int `json:"wait_timer,omitempty"` + Reviewers []*EnvReviewers `json:"reviewers,omitempty"` + DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy,omitempty"` + // Return/response only values + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + ProtectionRules []*ProtectionRule `json:"protection_rules,omitempty"` +} + +// EnvReviewers represents a single environment reviewer entry. +type EnvReviewers struct { + Type *string `json:"type,omitempty"` + ID *int64 `json:"id,omitempty"` +} + +// BranchPolicy represents the options for whether a branch deployment policy is applied to this environment. +type BranchPolicy struct { + ProtectedBranches *bool `json:"protected_branches,omitempty"` + CustomBranchPolicies *bool `json:"custom_branch_policies,omitempty"` +} + +// EnvResponse represents the slightly different format of response that comes back when you list an environment. +type EnvResponse struct { + TotalCount *int `json:"total_count,omitempty"` + Environments []*Environment `json:"environments,omitempty"` +} + +// ProtectionRule represents a single protection rule applied to the environment. +type ProtectionRule struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Type *string `json:"type,omitempty"` + WaitTimer *int `json:"wait_timer,omitempty"` + Reviewers []*RequiredReviewer `json:"reviewers,omitempty"` +} + +// RequiredReviewer represents a required reviewer. +type RequiredReviewer struct { + Type *string `json:"type,omitempty"` + Reviewer interface{} `json:"reviewer,omitempty"` +} + +// EnvironmentListOptions specifies the optional parameters to the +// RepositoriesService.ListEnvironments method. +type EnvironmentListOptions struct { + ListOptions +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// This helps us handle the fact that RequiredReviewer can have either a User or Team type reviewer field. +func (r *RequiredReviewer) UnmarshalJSON(data []byte) error { + type aliasReviewer RequiredReviewer + var reviewer aliasReviewer + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + + r.Type = reviewer.Type + + switch *reviewer.Type { + case "User": + reviewer.Reviewer = &User{} + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + r.Reviewer = reviewer.Reviewer + case "Team": + reviewer.Reviewer = &Team{} + if err := json.Unmarshal(data, &reviewer); err != nil { + return err + } + r.Reviewer = reviewer.Reviewer + default: + r.Type = nil + r.Reviewer = nil + return fmt.Errorf("reviewer.Type is %T, not a string of 'User' or 'Team', unable to unmarshal", reviewer.Type) + } + + return nil +} + +// ListEnvironments lists all environments for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/environments#get-all-environments +func (s *RepositoriesService) ListEnvironments(ctx context.Context, owner, repo string, opts *EnvironmentListOptions) (*EnvResponse, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var list *EnvResponse + resp, err := s.client.Do(ctx, req, &list) + if err != nil { + return nil, resp, err + } + return list, resp, nil +} + +// GetEnvironment get a single environment for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/environments#get-an-environment +func (s *RepositoriesService) GetEnvironment(ctx context.Context, owner, repo, name string) (*Environment, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var env *Environment + resp, err := s.client.Do(ctx, req, &env) + if err != nil { + return nil, resp, err + } + return env, resp, nil +} + +// MarshalJSON implements the json.Marshaler interface. +// As the only way to clear a WaitTimer is to set it to 0, a missing WaitTimer object should default to 0, not null. +func (c *CreateUpdateEnvironment) MarshalJSON() ([]byte, error) { + type Alias CreateUpdateEnvironment + if c.WaitTimer == nil { + c.WaitTimer = Int(0) + } + return json.Marshal(&struct { + *Alias + }{ + Alias: (*Alias)(c), + }) +} + +// CreateUpdateEnvironment represents the fields required for the create/update operation +// following the Create/Update release example. +// See https://github.com/google/go-github/issues/992 for more information. +// Removed omitempty here as the API expects null values for reviewers and deployment_branch_policy to clear them. +type CreateUpdateEnvironment struct { + WaitTimer *int `json:"wait_timer"` + Reviewers []*EnvReviewers `json:"reviewers"` + DeploymentBranchPolicy *BranchPolicy `json:"deployment_branch_policy"` +} + +// CreateUpdateEnvironment create or update a new environment for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/environments#create-or-update-an-environment +func (s *RepositoriesService) CreateUpdateEnvironment(ctx context.Context, owner, repo, name string, environment *CreateUpdateEnvironment) (*Environment, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("PUT", u, environment) + if err != nil { + return nil, nil, err + } + + e := new(Environment) + resp, err := s.client.Do(ctx, req, e) + if err != nil { + return nil, resp, err + } + return e, resp, nil +} + +// DeleteEnvironment delete an environment from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deployments/environments#delete-an-environment +func (s *RepositoriesService) DeleteEnvironment(ctx context.Context, owner, repo, name string) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/environments/%s", owner, repo, name) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_forks.go b/vendor/github.com/google/go-github/v45/github/repos_forks.go new file mode 100644 index 0000000000..97bb328ffb --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_forks.go @@ -0,0 +1,96 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + + "encoding/json" +) + +// RepositoryListForksOptions specifies the optional parameters to the +// RepositoriesService.ListForks method. +type RepositoryListForksOptions struct { + // How to sort the forks list. Possible values are: newest, oldest, + // watchers. Default is "newest". + Sort string `url:"sort,omitempty"` + + ListOptions +} + +// ListForks lists the forks of the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/forks#list-forks +func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opts *RepositoryListForksOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// RepositoryCreateForkOptions specifies the optional parameters to the +// RepositoriesService.CreateFork method. +type RepositoryCreateForkOptions struct { + // The organization to fork the repository into. + Organization string `url:"organization,omitempty"` +} + +// CreateFork creates a fork of the specified repository. +// +// This method might return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing creating the fork in a background task. In this event, +// the Repository value will be returned, which includes the details about the pending fork. +// A follow up request, after a delay of a second or so, should result +// in a successful request. +// +// GitHub API docs: https://docs.github.com/en/rest/repos/forks#create-a-fork +func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opts *RepositoryCreateForkOptions) (*Repository, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/forks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + fork := new(Repository) + resp, err := s.client.Do(ctx, req, fork) + if err != nil { + // Persist AcceptedError's metadata to the Repository object. + if aerr, ok := err.(*AcceptedError); ok { + if err := json.Unmarshal(aerr.Raw, fork); err != nil { + return fork, resp, err + } + + return fork, resp, err + } + return nil, resp, err + } + + return fork, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_hooks.go b/vendor/github.com/google/go-github/v45/github/repos_hooks.go new file mode 100644 index 0000000000..4e738cfe8c --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_hooks.go @@ -0,0 +1,199 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// WebHookPayload represents the data that is received from GitHub when a push +// event hook is triggered. The format of these payloads pre-date most of the +// GitHub v3 API, so there are lots of minor incompatibilities with the types +// defined in the rest of the API. Therefore, several types are duplicated +// here to account for these differences. +// +// GitHub API docs: https://help.github.com/articles/post-receive-hooks +// +// Deprecated: Please use PushEvent instead. +type WebHookPayload = PushEvent + +// WebHookCommit represents the commit variant we receive from GitHub in a +// WebHookPayload. +// +// Deprecated: Please use HeadCommit instead. +type WebHookCommit = HeadCommit + +// WebHookAuthor represents the author or committer of a commit, as specified +// in a WebHookCommit. The commit author may not correspond to a GitHub User. +// +// Deprecated: Please use CommitAuthor instead. +// NOTE Breaking API change: the `Username` field is now called `Login`. +type WebHookAuthor = CommitAuthor + +// Hook represents a GitHub (web and service) hook for a repository. +type Hook struct { + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + ID *int64 `json:"id,omitempty"` + Type *string `json:"type,omitempty"` + Name *string `json:"name,omitempty"` + TestURL *string `json:"test_url,omitempty"` + PingURL *string `json:"ping_url,omitempty"` + LastResponse map[string]interface{} `json:"last_response,omitempty"` + + // Only the following fields are used when creating a hook. + // Config is required. + Config map[string]interface{} `json:"config,omitempty"` + Events []string `json:"events,omitempty"` + Active *bool `json:"active,omitempty"` +} + +func (h Hook) String() string { + return Stringify(h) +} + +// createHookRequest is a subset of Hook and is used internally +// by CreateHook to pass only the known fields for the endpoint. +// +// See https://github.com/google/go-github/issues/1015 for more +// information. +type createHookRequest struct { + // Config is required. + Name string `json:"name"` + Config map[string]interface{} `json:"config,omitempty"` + Events []string `json:"events,omitempty"` + Active *bool `json:"active,omitempty"` +} + +// CreateHook creates a Hook for the specified repository. +// Config is a required field. +// +// Note that only a subset of the hook fields are used and hook must +// not be nil. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#create-a-repository-webhook +func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + + hookReq := &createHookRequest{ + Name: "web", + Events: hook.Events, + Active: hook.Active, + Config: hook.Config, + } + + req, err := s.client.NewRequest("POST", u, hookReq) + if err != nil { + return nil, nil, err + } + + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// ListHooks lists all Hooks for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#list-repository-webhooks +func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var hooks []*Hook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetHook returns a single specified Hook. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#get-a-repository-webhook +func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// EditHook updates a specified Hook. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#update-a-repository-webhook +func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + h := new(Hook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// DeleteHook deletes a specified Hook. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#delete-a-repository-webhook +func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// PingHook triggers a 'ping' event to be sent to the Hook. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#ping-a-repository-webhook +func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// TestHook triggers a test Hook by github. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repos#test-the-push-repository-webhook +func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_hooks_deliveries.go b/vendor/github.com/google/go-github/v45/github/repos_hooks_deliveries.go new file mode 100644 index 0000000000..cbd2d3819a --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_hooks_deliveries.go @@ -0,0 +1,136 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// HookDelivery represents the data that is received from GitHub's Webhook Delivery API +// +// GitHub API docs: +// - https://docs.github.com/en/rest/webhooks/repo-deliveries#list-deliveries-for-a-repository-webhook +// - https://docs.github.com/en/rest/webhooks/repo-deliveries#get-a-delivery-for-a-repository-webhook +type HookDelivery struct { + ID *int64 `json:"id,omitempty"` + GUID *string `json:"guid,omitempty"` + DeliveredAt *Timestamp `json:"delivered_at,omitempty"` + Redelivery *bool `json:"redelivery,omitempty"` + Duration *float64 `json:"duration,omitempty"` + Status *string `json:"status,omitempty"` + StatusCode *int `json:"status_code,omitempty"` + Event *string `json:"event,omitempty"` + Action *string `json:"action,omitempty"` + InstallationID *int64 `json:"installation_id,omitempty"` + RepositoryID *int64 `json:"repository_id,omitempty"` + + // Request is populated by GetHookDelivery. + Request *HookRequest `json:"request,omitempty"` + // Response is populated by GetHookDelivery. + Response *HookResponse `json:"response,omitempty"` +} + +func (d HookDelivery) String() string { + return Stringify(d) +} + +// HookRequest is a part of HookDelivery that contains +// the HTTP headers and the JSON payload of the webhook request. +type HookRequest struct { + Headers map[string]string `json:"headers,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` +} + +func (r HookRequest) String() string { + return Stringify(r) +} + +// HookResponse is a part of HookDelivery that contains +// the HTTP headers and the response body served by the webhook endpoint. +type HookResponse struct { + Headers map[string]string `json:"headers,omitempty"` + RawPayload *json.RawMessage `json:"payload,omitempty"` +} + +func (r HookResponse) String() string { + return Stringify(r) +} + +// ListHookDeliveries lists webhook deliveries for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repo-deliveries#list-deliveries-for-a-repository-webhook +func (s *RepositoriesService) ListHookDeliveries(ctx context.Context, owner, repo string, id int64, opts *ListCursorOptions) ([]*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + deliveries := []*HookDelivery{} + resp, err := s.client.Do(ctx, req, &deliveries) + if err != nil { + return nil, resp, err + } + + return deliveries, resp, nil +} + +// GetHookDelivery returns a delivery for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repo-deliveries#get-a-delivery-for-a-repository-webhook +func (s *RepositoriesService) GetHookDelivery(ctx context.Context, owner, repo string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries/%v", owner, repo, hookID, deliveryID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// RedeliverHookDelivery redelivers a delivery for a webhook configured in a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/webhooks/repo-deliveries#redeliver-a-delivery-for-a-repository-webhook +func (s *RepositoriesService) RedeliverHookDelivery(ctx context.Context, owner, repo string, hookID, deliveryID int64) (*HookDelivery, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/hooks/%v/deliveries/%v/attempts", owner, repo, hookID, deliveryID) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + h := new(HookDelivery) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// ParseRequestPayload parses the request payload. For recognized event types, +// a value of the corresponding struct type will be returned. +func (d *HookDelivery) ParseRequestPayload() (interface{}, error) { + eType, ok := eventTypeMapping[*d.Event] + if !ok { + return nil, fmt.Errorf("unsupported event type %q", *d.Event) + } + + e := &Event{Type: &eType, RawPayload: d.Request.RawPayload} + return e.ParsePayload() +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_invitations.go b/vendor/github.com/google/go-github/v45/github/repos_invitations.go new file mode 100644 index 0000000000..81956cd49c --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_invitations.go @@ -0,0 +1,89 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryInvitation represents an invitation to collaborate on a repo. +type RepositoryInvitation struct { + ID *int64 `json:"id,omitempty"` + Repo *Repository `json:"repository,omitempty"` + Invitee *User `json:"invitee,omitempty"` + Inviter *User `json:"inviter,omitempty"` + + // Permissions represents the permissions that the associated user will have + // on the repository. Possible values are: "read", "write", "admin". + Permissions *string `json:"permissions,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` +} + +// ListInvitations lists all currently-open repository invitations. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/invitations#list-repository-invitations +func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryInvitation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + invites := []*RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, &invites) + if err != nil { + return nil, resp, err + } + + return invites, resp, nil +} + +// DeleteInvitation deletes a repository invitation. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/invitations#delete-a-repository-invitation +func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo string, invitationID int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UpdateInvitation updates the permissions associated with a repository +// invitation. +// +// permissions represents the permissions that the associated user will have +// on the repository. Possible values are: "read", "write", "admin". +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/invitations#update-a-repository-invitation +func (s *RepositoriesService) UpdateInvitation(ctx context.Context, owner, repo string, invitationID int64, permissions string) (*RepositoryInvitation, *Response, error) { + opts := &struct { + Permissions string `json:"permissions"` + }{Permissions: permissions} + u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID) + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + invite := &RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, invite) + if err != nil { + return nil, resp, err + } + + return invite, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_keys.go b/vendor/github.com/google/go-github/v45/github/repos_keys.go new file mode 100644 index 0000000000..42c5de4970 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_keys.go @@ -0,0 +1,91 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// The Key type is defined in users_keys.go + +// ListKeys lists the deploy keys for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deploy-keys#list-deploy-keys +func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*Key + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetKey fetches a single deploy key. +// +// GitHub API docs: https://docs.github.com/en/rest/deploy-keys#get-a-deploy-key +func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo string, id int64) (*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := new(Key) + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateKey adds a deploy key for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/deploy-keys#create-a-deploy-key +func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo string, key *Key) (*Key, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys", owner, repo) + + req, err := s.client.NewRequest("POST", u, key) + if err != nil { + return nil, nil, err + } + + k := new(Key) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// DeleteKey deletes a deploy key. +// +// GitHub API docs: https://docs.github.com/en/rest/deploy-keys#delete-a-deploy-key +func (s *RepositoriesService) DeleteKey(ctx context.Context, owner string, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_merging.go b/vendor/github.com/google/go-github/v45/github/repos_merging.go new file mode 100644 index 0000000000..66e88452e8 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_merging.go @@ -0,0 +1,72 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// RepositoryMergeRequest represents a request to merge a branch in a +// repository. +type RepositoryMergeRequest struct { + Base *string `json:"base,omitempty"` + Head *string `json:"head,omitempty"` + CommitMessage *string `json:"commit_message,omitempty"` +} + +// RepoMergeUpstreamRequest represents a request to sync a branch of +// a forked repository to keep it up-to-date with the upstream repository. +type RepoMergeUpstreamRequest struct { + Branch *string `json:"branch,omitempty"` +} + +// RepoMergeUpstreamResult represents the result of syncing a branch of +// a forked repository with the upstream repository. +type RepoMergeUpstreamResult struct { + Message *string `json:"message,omitempty"` + MergeType *string `json:"merge_type,omitempty"` + BaseBranch *string `json:"base_branch,omitempty"` +} + +// Merge a branch in the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branches#merge-a-branch +func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/merges", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + commit := new(RepositoryCommit) + resp, err := s.client.Do(ctx, req, commit) + if err != nil { + return nil, resp, err + } + + return commit, resp, nil +} + +// MergeUpstream syncs a branch of a forked repository to keep it up-to-date +// with the upstream repository. +// +// GitHub API docs: https://docs.github.com/en/rest/branches/branches#sync-a-fork-branch-with-the-upstream-repository +func (s *RepositoriesService) MergeUpstream(ctx context.Context, owner, repo string, request *RepoMergeUpstreamRequest) (*RepoMergeUpstreamResult, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/merge-upstream", owner, repo) + req, err := s.client.NewRequest("POST", u, request) + if err != nil { + return nil, nil, err + } + + result := new(RepoMergeUpstreamResult) + resp, err := s.client.Do(ctx, req, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_pages.go b/vendor/github.com/google/go-github/v45/github/repos_pages.go new file mode 100644 index 0000000000..9b864eb090 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_pages.go @@ -0,0 +1,240 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Pages represents a GitHub Pages site configuration. +type Pages struct { + URL *string `json:"url,omitempty"` + Status *string `json:"status,omitempty"` + CNAME *string `json:"cname,omitempty"` + Custom404 *bool `json:"custom_404,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Source *PagesSource `json:"source,omitempty"` + Public *bool `json:"public,omitempty"` + HTTPSCertificate *PagesHTTPSCertificate `json:"https_certificate,omitempty"` + HTTPSEnforced *bool `json:"https_enforced,omitempty"` +} + +// PagesSource represents a GitHub page's source. +type PagesSource struct { + Branch *string `json:"branch,omitempty"` + Path *string `json:"path,omitempty"` +} + +// PagesError represents a build error for a GitHub Pages site. +type PagesError struct { + Message *string `json:"message,omitempty"` +} + +// PagesBuild represents the build information for a GitHub Pages site. +type PagesBuild struct { + URL *string `json:"url,omitempty"` + Status *string `json:"status,omitempty"` + Error *PagesError `json:"error,omitempty"` + Pusher *User `json:"pusher,omitempty"` + Commit *string `json:"commit,omitempty"` + Duration *int `json:"duration,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` +} + +// PagesHTTPSCertificate represents the HTTPS Certificate information for a GitHub Pages site. +type PagesHTTPSCertificate struct { + State *string `json:"state,omitempty"` + Description *string `json:"description,omitempty"` + Domains []string `json:"domains,omitempty"` + // GitHub's API doesn't return a standard Timestamp, rather it returns a YYYY-MM-DD string. + ExpiresAt *string `json:"expires_at,omitempty"` +} + +// createPagesRequest is a subset of Pages and is used internally +// by EnablePages to pass only the known fields for the endpoint. +type createPagesRequest struct { + Source *PagesSource `json:"source,omitempty"` +} + +// EnablePages enables GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/en/rest/pages#create-a-github-pages-site +func (s *RepositoriesService) EnablePages(ctx context.Context, owner, repo string, pages *Pages) (*Pages, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + + pagesReq := &createPagesRequest{ + Source: pages.Source, + } + + req, err := s.client.NewRequest("POST", u, pagesReq) + if err != nil { + return nil, nil, err + } + + req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview) + + enable := new(Pages) + resp, err := s.client.Do(ctx, req, enable) + if err != nil { + return nil, resp, err + } + + return enable, resp, nil +} + +// PagesUpdate sets up parameters needed to update a GitHub Pages site. +type PagesUpdate struct { + // CNAME represents a custom domain for the repository. + // Leaving CNAME empty will remove the custom domain. + CNAME *string `json:"cname"` + // Source must include the branch name, and may optionally specify the subdirectory "/docs". + // Possible values are: "gh-pages", "master", and "master /docs". + Source *string `json:"source,omitempty"` + // Public configures access controls for the site. + // If "true", the site will be accessible to anyone on the internet. If "false", + // the site will be accessible to anyone with read access to the repository that + // published the site. + Public *bool `json:"public,omitempty"` + // HTTPSEnforced specifies whether HTTPS should be enforced for the repository. + HTTPSEnforced *bool `json:"https_enforced,omitempty"` +} + +// UpdatePages updates GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/en/rest/pages#update-information-about-a-github-pages-site +func (s *RepositoriesService) UpdatePages(ctx context.Context, owner, repo string, opts *PagesUpdate) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + + return resp, nil +} + +// DisablePages disables GitHub Pages for the named repo. +// +// GitHub API docs: https://docs.github.com/en/rest/pages#delete-a-github-pages-site +func (s *RepositoriesService) DisablePages(ctx context.Context, owner, repo string) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview) + + return s.client.Do(ctx, req, nil) +} + +// GetPagesInfo fetches information about a GitHub Pages site. +// +// GitHub API docs: https://docs.github.com/en/rest/pages#get-a-github-pages-site +func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + site := new(Pages) + resp, err := s.client.Do(ctx, req, site) + if err != nil { + return nil, resp, err + } + + return site, resp, nil +} + +// ListPagesBuilds lists the builds for a GitHub Pages site. +// +// GitHub API docs: https://docs.github.com/en/rest/pages#list-github-pages-builds +func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pages []*PagesBuild + resp, err := s.client.Do(ctx, req, &pages) + if err != nil { + return nil, resp, err + } + + return pages, resp, nil +} + +// GetLatestPagesBuild fetches the latest build information for a GitHub pages site. +// +// GitHub API docs: https://docs.github.com/en/rest/pages#get-latest-pages-build +func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// GetPageBuild fetches the specific build information for a GitHub pages site. +// +// GitHub API docs: https://docs.github.com/en/rest/pages#get-github-pages-build +func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} + +// RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit. +// +// GitHub API docs: https://docs.github.com/en/rest/pages#request-a-github-pages-build +func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo) + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, nil, err + } + + build := new(PagesBuild) + resp, err := s.client.Do(ctx, req, build) + if err != nil { + return nil, resp, err + } + + return build, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_prereceive_hooks.go b/vendor/github.com/google/go-github/v45/github/repos_prereceive_hooks.go new file mode 100644 index 0000000000..1ce6478d33 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_prereceive_hooks.go @@ -0,0 +1,110 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// PreReceiveHook represents a GitHub pre-receive hook for a repository. +type PreReceiveHook struct { + ID *int64 `json:"id,omitempty"` + Name *string `json:"name,omitempty"` + Enforcement *string `json:"enforcement,omitempty"` + ConfigURL *string `json:"configuration_url,omitempty"` +} + +func (p PreReceiveHook) String() string { + return Stringify(p) +} + +// ListPreReceiveHooks lists all pre-receive hooks for the specified repository. +// +// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#list-pre-receive-hooks +func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PreReceiveHook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) + + var hooks []*PreReceiveHook + resp, err := s.client.Do(ctx, req, &hooks) + if err != nil { + return nil, resp, err + } + + return hooks, resp, nil +} + +// GetPreReceiveHook returns a single specified pre-receive hook. +// +// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#get-a-single-pre-receive-hook +func (s *RepositoriesService) GetPreReceiveHook(ctx context.Context, owner, repo string, id int64) (*PreReceiveHook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) + + h := new(PreReceiveHook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// UpdatePreReceiveHook updates a specified pre-receive hook. +// +// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#update-pre-receive-hook-enforcement +func (s *RepositoriesService) UpdatePreReceiveHook(ctx context.Context, owner, repo string, id int64, hook *PreReceiveHook) (*PreReceiveHook, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("PATCH", u, hook) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) + + h := new(PreReceiveHook) + resp, err := s.client.Do(ctx, req, h) + if err != nil { + return nil, resp, err + } + + return h, resp, nil +} + +// DeletePreReceiveHook deletes a specified pre-receive hook. +// +// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#remove-enforcement-overrides-for-a-pre-receive-hook +func (s *RepositoriesService) DeletePreReceiveHook(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypePreReceiveHooksPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_projects.go b/vendor/github.com/google/go-github/v45/github/repos_projects.go new file mode 100644 index 0000000000..a3001dee98 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_projects.go @@ -0,0 +1,69 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ProjectListOptions specifies the optional parameters to the +// OrganizationsService.ListProjects and RepositoriesService.ListProjects methods. +type ProjectListOptions struct { + // Indicates the state of the projects to return. Can be either open, closed, or all. Default: open + State string `url:"state,omitempty"` + + ListOptions +} + +// ListProjects lists the projects for a repo. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#list-repository-projects +func (s *RepositoriesService) ListProjects(ctx context.Context, owner, repo string, opts *ProjectListOptions) ([]*Project, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var projects []*Project + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// CreateProject creates a GitHub Project for the specified repository. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#create-a-repository-project +func (s *RepositoriesService) CreateProject(ctx context.Context, owner, repo string, opts *ProjectOptions) (*Project, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/projects", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept headers when APIs fully launch. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_releases.go b/vendor/github.com/google/go-github/v45/github/repos_releases.go new file mode 100644 index 0000000000..f1ab65c185 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_releases.go @@ -0,0 +1,441 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "errors" + "fmt" + "io" + "mime" + "net/http" + "os" + "path/filepath" + "strings" +) + +// RepositoryRelease represents a GitHub release in a repository. +type RepositoryRelease struct { + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + DiscussionCategoryName *string `json:"discussion_category_name,omitempty"` + GenerateReleaseNotes *bool `json:"generate_release_notes,omitempty"` + + // The following fields are not used in CreateRelease or EditRelease: + ID *int64 `json:"id,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + PublishedAt *Timestamp `json:"published_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + AssetsURL *string `json:"assets_url,omitempty"` + Assets []*ReleaseAsset `json:"assets,omitempty"` + UploadURL *string `json:"upload_url,omitempty"` + ZipballURL *string `json:"zipball_url,omitempty"` + TarballURL *string `json:"tarball_url,omitempty"` + Author *User `json:"author,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r RepositoryRelease) String() string { + return Stringify(r) +} + +// RepositoryReleaseNotes represents a GitHub-generated release notes. +type RepositoryReleaseNotes struct { + Name string `json:"name"` + Body string `json:"body"` +} + +// GenerateNotesOptions represents the options to generate release notes. +type GenerateNotesOptions struct { + TagName string `json:"tag_name"` + PreviousTagName *string `json:"previous_tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` +} + +// ReleaseAsset represents a GitHub release asset in a repository. +type ReleaseAsset struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Label *string `json:"label,omitempty"` + State *string `json:"state,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Size *int `json:"size,omitempty"` + DownloadCount *int `json:"download_count,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + BrowserDownloadURL *string `json:"browser_download_url,omitempty"` + Uploader *User `json:"uploader,omitempty"` + NodeID *string `json:"node_id,omitempty"` +} + +func (r ReleaseAsset) String() string { + return Stringify(r) +} + +// ListReleases lists the releases for a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/releases#list-releases +func (s *RepositoriesService) ListReleases(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var releases []*RepositoryRelease + resp, err := s.client.Do(ctx, req, &releases) + if err != nil { + return nil, resp, err + } + return releases, resp, nil +} + +// GetRelease fetches a single release. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/releases#get-a-release +func (s *RepositoriesService) GetRelease(ctx context.Context, owner, repo string, id int64) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + return s.getSingleRelease(ctx, u) +} + +// GetLatestRelease fetches the latest published release for the repository. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/releases#get-the-latest-release +func (s *RepositoriesService) GetLatestRelease(ctx context.Context, owner, repo string) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/latest", owner, repo) + return s.getSingleRelease(ctx, u) +} + +// GetReleaseByTag fetches a release with the specified tag. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/releases#get-a-release-by-tag-name +func (s *RepositoriesService) GetReleaseByTag(ctx context.Context, owner, repo, tag string) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/tags/%s", owner, repo, tag) + return s.getSingleRelease(ctx, u) +} + +// GenerateReleaseNotes generates the release notes for the given tag. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/releases#generate-release-notes-content-for-a-release +func (s *RepositoriesService) GenerateReleaseNotes(ctx context.Context, owner, repo string, opts *GenerateNotesOptions) (*RepositoryReleaseNotes, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/generate-notes", owner, repo) + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + r := new(RepositoryReleaseNotes) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + + return r, resp, nil +} + +func (s *RepositoriesService) getSingleRelease(ctx context.Context, url string) (*RepositoryRelease, *Response, error) { + req, err := s.client.NewRequest("GET", url, nil) + if err != nil { + return nil, nil, err + } + + release := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, release) + if err != nil { + return nil, resp, err + } + return release, resp, nil +} + +// repositoryReleaseRequest is a subset of RepositoryRelease and +// is used internally by CreateRelease and EditRelease to pass +// only the known fields for these endpoints. +// +// See https://github.com/google/go-github/issues/992 for more +// information. +type repositoryReleaseRequest struct { + TagName *string `json:"tag_name,omitempty"` + TargetCommitish *string `json:"target_commitish,omitempty"` + Name *string `json:"name,omitempty"` + Body *string `json:"body,omitempty"` + Draft *bool `json:"draft,omitempty"` + Prerelease *bool `json:"prerelease,omitempty"` + GenerateReleaseNotes *bool `json:"generate_release_notes,omitempty"` + DiscussionCategoryName *string `json:"discussion_category_name,omitempty"` +} + +// CreateRelease adds a new release for a repository. +// +// Note that only a subset of the release fields are used. +// See RepositoryRelease for more information. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/releases#create-a-release +func (s *RepositoriesService) CreateRelease(ctx context.Context, owner, repo string, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases", owner, repo) + + releaseReq := &repositoryReleaseRequest{ + TagName: release.TagName, + TargetCommitish: release.TargetCommitish, + Name: release.Name, + Body: release.Body, + Draft: release.Draft, + Prerelease: release.Prerelease, + DiscussionCategoryName: release.DiscussionCategoryName, + GenerateReleaseNotes: release.GenerateReleaseNotes, + } + + req, err := s.client.NewRequest("POST", u, releaseReq) + if err != nil { + return nil, nil, err + } + + r := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + return r, resp, nil +} + +// EditRelease edits a repository release. +// +// Note that only a subset of the release fields are used. +// See RepositoryRelease for more information. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/releases#update-a-release +func (s *RepositoriesService) EditRelease(ctx context.Context, owner, repo string, id int64, release *RepositoryRelease) (*RepositoryRelease, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + + releaseReq := &repositoryReleaseRequest{ + TagName: release.TagName, + TargetCommitish: release.TargetCommitish, + Name: release.Name, + Body: release.Body, + Draft: release.Draft, + Prerelease: release.Prerelease, + DiscussionCategoryName: release.DiscussionCategoryName, + GenerateReleaseNotes: release.GenerateReleaseNotes, + } + + req, err := s.client.NewRequest("PATCH", u, releaseReq) + if err != nil { + return nil, nil, err + } + + r := new(RepositoryRelease) + resp, err := s.client.Do(ctx, req, r) + if err != nil { + return nil, resp, err + } + return r, resp, nil +} + +// DeleteRelease delete a single release from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/releases#delete-a-release +func (s *RepositoriesService) DeleteRelease(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ListReleaseAssets lists the release's assets. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/assets#list-release-assets +func (s *RepositoriesService) ListReleaseAssets(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var assets []*ReleaseAsset + resp, err := s.client.Do(ctx, req, &assets) + if err != nil { + return nil, resp, err + } + return assets, resp, nil +} + +// GetReleaseAsset fetches a single release asset. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/assets#get-a-release-asset +func (s *RepositoriesService) GetReleaseAsset(ctx context.Context, owner, repo string, id int64) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} + +// DownloadReleaseAsset downloads a release asset or returns a redirect URL. +// +// DownloadReleaseAsset returns an io.ReadCloser that reads the contents of the +// specified release asset. It is the caller's responsibility to close the ReadCloser. +// If a redirect is returned, the redirect URL will be returned as a string instead +// of the io.ReadCloser. Exactly one of rc and redirectURL will be zero. +// +// followRedirectsClient can be passed to download the asset from a redirected +// location. Passing http.DefaultClient is recommended unless special circumstances +// exist, but it's possible to pass any http.Client. If nil is passed the +// redirectURL will be returned instead. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/assets#get-a-release-asset +func (s *RepositoriesService) DownloadReleaseAsset(ctx context.Context, owner, repo string, id int64, followRedirectsClient *http.Client) (rc io.ReadCloser, redirectURL string, err error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, "", err + } + req.Header.Set("Accept", defaultMediaType) + + s.client.clientMu.Lock() + defer s.client.clientMu.Unlock() + + var loc string + saveRedirect := s.client.client.CheckRedirect + s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + loc = req.URL.String() + return errors.New("disable redirect") + } + defer func() { s.client.client.CheckRedirect = saveRedirect }() + + req = withContext(ctx, req) + resp, err := s.client.client.Do(req) + if err != nil { + if !strings.Contains(err.Error(), "disable redirect") { + return nil, "", err + } + if followRedirectsClient != nil { + rc, err := s.downloadReleaseAssetFromURL(ctx, followRedirectsClient, loc) + return rc, "", err + } + return nil, loc, nil // Intentionally return no error with valid redirect URL. + } + + if err := CheckResponse(resp); err != nil { + resp.Body.Close() + return nil, "", err + } + + return resp.Body, "", nil +} + +func (s *RepositoriesService) downloadReleaseAssetFromURL(ctx context.Context, followRedirectsClient *http.Client, url string) (rc io.ReadCloser, err error) { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return nil, err + } + req = withContext(ctx, req) + req.Header.Set("Accept", "*/*") + resp, err := followRedirectsClient.Do(req) + if err != nil { + return nil, err + } + if err := CheckResponse(resp); err != nil { + resp.Body.Close() + return nil, err + } + return resp.Body, nil +} + +// EditReleaseAsset edits a repository release asset. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/assets#update-a-release-asset +func (s *RepositoriesService) EditReleaseAsset(ctx context.Context, owner, repo string, id int64, release *ReleaseAsset) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("PATCH", u, release) + if err != nil { + return nil, nil, err + } + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} + +// DeleteReleaseAsset delete a single release asset from a repository. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/assets#delete-a-release-asset +func (s *RepositoriesService) DeleteReleaseAsset(ctx context.Context, owner, repo string, id int64) (*Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/assets/%d", owner, repo, id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// UploadReleaseAsset creates an asset by uploading a file into a release repository. +// To upload assets that cannot be represented by an os.File, call NewUploadRequest directly. +// +// GitHub API docs: https://docs.github.com/en/rest/releases/assets#upload-a-release-asset +func (s *RepositoriesService) UploadReleaseAsset(ctx context.Context, owner, repo string, id int64, opts *UploadOptions, file *os.File) (*ReleaseAsset, *Response, error) { + u := fmt.Sprintf("repos/%s/%s/releases/%d/assets", owner, repo, id) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + stat, err := file.Stat() + if err != nil { + return nil, nil, err + } + if stat.IsDir() { + return nil, nil, errors.New("the asset to upload can't be a directory") + } + + mediaType := mime.TypeByExtension(filepath.Ext(file.Name())) + if opts.MediaType != "" { + mediaType = opts.MediaType + } + + req, err := s.client.NewUploadRequest(u, file, stat.Size(), mediaType) + if err != nil { + return nil, nil, err + } + + asset := new(ReleaseAsset) + resp, err := s.client.Do(ctx, req, asset) + if err != nil { + return nil, resp, err + } + return asset, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_stats.go b/vendor/github.com/google/go-github/v45/github/repos_stats.go new file mode 100644 index 0000000000..3df0a8f6de --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_stats.go @@ -0,0 +1,232 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// ContributorStats represents a contributor to a repository and their +// weekly contributions to a given repo. +type ContributorStats struct { + Author *Contributor `json:"author,omitempty"` + Total *int `json:"total,omitempty"` + Weeks []*WeeklyStats `json:"weeks,omitempty"` +} + +func (c ContributorStats) String() string { + return Stringify(c) +} + +// WeeklyStats represents the number of additions, deletions and commits +// a Contributor made in a given week. +type WeeklyStats struct { + Week *Timestamp `json:"w,omitempty"` + Additions *int `json:"a,omitempty"` + Deletions *int `json:"d,omitempty"` + Commits *int `json:"c,omitempty"` +} + +func (w WeeklyStats) String() string { + return Stringify(w) +} + +// ListContributorsStats gets a repo's contributor list with additions, +// deletions and commit counts. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/statistics#get-all-contributor-commit-activity +func (s *RepositoriesService) ListContributorsStats(ctx context.Context, owner, repo string) ([]*ContributorStats, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/contributors", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var contributorStats []*ContributorStats + resp, err := s.client.Do(ctx, req, &contributorStats) + if err != nil { + return nil, resp, err + } + + return contributorStats, resp, nil +} + +// WeeklyCommitActivity represents the weekly commit activity for a repository. +// The days array is a group of commits per day, starting on Sunday. +type WeeklyCommitActivity struct { + Days []int `json:"days,omitempty"` + Total *int `json:"total,omitempty"` + Week *Timestamp `json:"week,omitempty"` +} + +func (w WeeklyCommitActivity) String() string { + return Stringify(w) +} + +// ListCommitActivity returns the last year of commit activity +// grouped by week. The days array is a group of commits per day, +// starting on Sunday. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/statistics#get-the-last-year-of-commit-activity +func (s *RepositoriesService) ListCommitActivity(ctx context.Context, owner, repo string) ([]*WeeklyCommitActivity, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/commit_activity", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var weeklyCommitActivity []*WeeklyCommitActivity + resp, err := s.client.Do(ctx, req, &weeklyCommitActivity) + if err != nil { + return nil, resp, err + } + + return weeklyCommitActivity, resp, nil +} + +// ListCodeFrequency returns a weekly aggregate of the number of additions and +// deletions pushed to a repository. Returned WeeklyStats will contain +// additions and deletions, but not total commits. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/statistics#get-the-weekly-commit-activity +func (s *RepositoriesService) ListCodeFrequency(ctx context.Context, owner, repo string) ([]*WeeklyStats, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/code_frequency", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var weeks [][]int + resp, err := s.client.Do(ctx, req, &weeks) + if err != nil { + return nil, resp, err + } + + // convert int slices into WeeklyStats + var stats []*WeeklyStats + for _, week := range weeks { + if len(week) != 3 { + continue + } + stat := &WeeklyStats{ + Week: &Timestamp{time.Unix(int64(week[0]), 0)}, + Additions: Int(week[1]), + Deletions: Int(week[2]), + } + stats = append(stats, stat) + } + + return stats, resp, nil +} + +// RepositoryParticipation is the number of commits by everyone +// who has contributed to the repository (including the owner) +// as well as the number of commits by the owner themself. +type RepositoryParticipation struct { + All []int `json:"all,omitempty"` + Owner []int `json:"owner,omitempty"` +} + +func (r RepositoryParticipation) String() string { + return Stringify(r) +} + +// ListParticipation returns the total commit counts for the 'owner' +// and total commit counts in 'all'. 'all' is everyone combined, +// including the 'owner' in the last 52 weeks. If you’d like to get +// the commit counts for non-owners, you can subtract 'all' from 'owner'. +// +// The array order is oldest week (index 0) to most recent week. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/statistics#get-the-weekly-commit-count +func (s *RepositoriesService) ListParticipation(ctx context.Context, owner, repo string) (*RepositoryParticipation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/participation", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + participation := new(RepositoryParticipation) + resp, err := s.client.Do(ctx, req, participation) + if err != nil { + return nil, resp, err + } + + return participation, resp, nil +} + +// PunchCard represents the number of commits made during a given hour of a +// day of the week. +type PunchCard struct { + Day *int // Day of the week (0-6: =Sunday - Saturday). + Hour *int // Hour of day (0-23). + Commits *int // Number of commits. +} + +// ListPunchCard returns the number of commits per hour in each day. +// +// If this is the first time these statistics are requested for the given +// repository, this method will return an *AcceptedError and a status code of +// 202. This is because this is the status that GitHub returns to signify that +// it is now computing the requested statistics. A follow up request, after a +// delay of a second or so, should result in a successful request. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/statistics#get-the-hourly-commit-count-for-each-day +func (s *RepositoriesService) ListPunchCard(ctx context.Context, owner, repo string) ([]*PunchCard, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/stats/punch_card", owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var results [][]int + resp, err := s.client.Do(ctx, req, &results) + if err != nil { + return nil, resp, err + } + + // convert int slices into Punchcards + var cards []*PunchCard + for _, result := range results { + if len(result) != 3 { + continue + } + card := &PunchCard{ + Day: Int(result[0]), + Hour: Int(result[1]), + Commits: Int(result[2]), + } + cards = append(cards, card) + } + + return cards, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_statuses.go b/vendor/github.com/google/go-github/v45/github/repos_statuses.go new file mode 100644 index 0000000000..42238f3c9d --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_statuses.go @@ -0,0 +1,133 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// RepoStatus represents the status of a repository at a particular reference. +type RepoStatus struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + URL *string `json:"url,omitempty"` + + // State is the current state of the repository. Possible values are: + // pending, success, error, or failure. + State *string `json:"state,omitempty"` + + // TargetURL is the URL of the page representing this status. It will be + // linked from the GitHub UI to allow users to see the source of the status. + TargetURL *string `json:"target_url,omitempty"` + + // Description is a short high level summary of the status. + Description *string `json:"description,omitempty"` + + // A string label to differentiate this status from the statuses of other systems. + Context *string `json:"context,omitempty"` + + // AvatarURL is the URL of the avatar of this status. + AvatarURL *string `json:"avatar_url,omitempty"` + + Creator *User `json:"creator,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` +} + +func (r RepoStatus) String() string { + return Stringify(r) +} + +// ListStatuses lists the statuses of a repository at the specified +// reference. ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/statuses#list-commit-statuses-for-a-reference +func (s *RepositoriesService) ListStatuses(ctx context.Context, owner, repo, ref string, opts *ListOptions) ([]*RepoStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/statuses", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var statuses []*RepoStatus + resp, err := s.client.Do(ctx, req, &statuses) + if err != nil { + return nil, resp, err + } + + return statuses, resp, nil +} + +// CreateStatus creates a new status for a repository at the specified +// reference. Ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/statuses#create-a-commit-status +func (s *RepositoriesService) CreateStatus(ctx context.Context, owner, repo, ref string, status *RepoStatus) (*RepoStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/statuses/%v", owner, repo, refURLEscape(ref)) + req, err := s.client.NewRequest("POST", u, status) + if err != nil { + return nil, nil, err + } + + repoStatus := new(RepoStatus) + resp, err := s.client.Do(ctx, req, repoStatus) + if err != nil { + return nil, resp, err + } + + return repoStatus, resp, nil +} + +// CombinedStatus represents the combined status of a repository at a particular reference. +type CombinedStatus struct { + // State is the combined state of the repository. Possible values are: + // failure, pending, or success. + State *string `json:"state,omitempty"` + + Name *string `json:"name,omitempty"` + SHA *string `json:"sha,omitempty"` + TotalCount *int `json:"total_count,omitempty"` + Statuses []*RepoStatus `json:"statuses,omitempty"` + + CommitURL *string `json:"commit_url,omitempty"` + RepositoryURL *string `json:"repository_url,omitempty"` +} + +func (s CombinedStatus) String() string { + return Stringify(s) +} + +// GetCombinedStatus returns the combined status of a repository at the specified +// reference. ref can be a SHA, a branch name, or a tag name. +// +// GitHub API docs: https://docs.github.com/en/rest/commits/statuses#get-the-combined-status-for-a-specific-reference +func (s *RepositoriesService) GetCombinedStatus(ctx context.Context, owner, repo, ref string, opts *ListOptions) (*CombinedStatus, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/commits/%v/status", owner, repo, refURLEscape(ref)) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + status := new(CombinedStatus) + resp, err := s.client.Do(ctx, req, status) + if err != nil { + return nil, resp, err + } + + return status, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/repos_traffic.go b/vendor/github.com/google/go-github/v45/github/repos_traffic.go new file mode 100644 index 0000000000..bf093c03ea --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/repos_traffic.go @@ -0,0 +1,141 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TrafficReferrer represent information about traffic from a referrer . +type TrafficReferrer struct { + Referrer *string `json:"referrer,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficPath represent information about the traffic on a path of the repo. +type TrafficPath struct { + Path *string `json:"path,omitempty"` + Title *string `json:"title,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficData represent information about a specific timestamp in views or clones list. +type TrafficData struct { + Timestamp *Timestamp `json:"timestamp,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficViews represent information about the number of views in the last 14 days. +type TrafficViews struct { + Views []*TrafficData `json:"views,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficClones represent information about the number of clones in the last 14 days. +type TrafficClones struct { + Clones []*TrafficData `json:"clones,omitempty"` + Count *int `json:"count,omitempty"` + Uniques *int `json:"uniques,omitempty"` +} + +// TrafficBreakdownOptions specifies the parameters to methods that support breakdown per day or week. +// Can be one of: day, week. Default: day. +type TrafficBreakdownOptions struct { + Per string `url:"per,omitempty"` +} + +// ListTrafficReferrers list the top 10 referrers over the last 14 days. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/traffic#get-top-referral-sources +func (s *RepositoriesService) ListTrafficReferrers(ctx context.Context, owner, repo string) ([]*TrafficReferrer, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/popular/referrers", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var trafficReferrers []*TrafficReferrer + resp, err := s.client.Do(ctx, req, &trafficReferrers) + if err != nil { + return nil, resp, err + } + + return trafficReferrers, resp, nil +} + +// ListTrafficPaths list the top 10 popular content over the last 14 days. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/traffic#get-top-referral-paths +func (s *RepositoriesService) ListTrafficPaths(ctx context.Context, owner, repo string) ([]*TrafficPath, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/popular/paths", owner, repo) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var paths []*TrafficPath + resp, err := s.client.Do(ctx, req, &paths) + if err != nil { + return nil, resp, err + } + + return paths, resp, nil +} + +// ListTrafficViews get total number of views for the last 14 days and breaks it down either per day or week. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/traffic#get-page-views +func (s *RepositoriesService) ListTrafficViews(ctx context.Context, owner, repo string, opts *TrafficBreakdownOptions) (*TrafficViews, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/views", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + trafficViews := new(TrafficViews) + resp, err := s.client.Do(ctx, req, &trafficViews) + if err != nil { + return nil, resp, err + } + + return trafficViews, resp, nil +} + +// ListTrafficClones get total number of clones for the last 14 days and breaks it down either per day or week for the last 14 days. +// +// GitHub API docs: https://docs.github.com/en/rest/metrics/traffic#get-repository-clones +func (s *RepositoriesService) ListTrafficClones(ctx context.Context, owner, repo string, opts *TrafficBreakdownOptions) (*TrafficClones, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/traffic/clones", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + trafficClones := new(TrafficClones) + resp, err := s.client.Do(ctx, req, &trafficClones) + if err != nil { + return nil, resp, err + } + + return trafficClones, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/scim.go b/vendor/github.com/google/go-github/v45/github/scim.go new file mode 100644 index 0000000000..c4abb9ab3e --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/scim.go @@ -0,0 +1,163 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "encoding/json" + "fmt" +) + +// SCIMService provides access to SCIM related functions in the +// GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/scim +type SCIMService service + +// SCIMUserAttributes represents supported SCIM User attributes. +// +// GitHub API docs: https://docs.github.com/en/rest/scim#supported-scim-user-attributes +type SCIMUserAttributes struct { + UserName string `json:"userName"` // Configured by the admin. Could be an email, login, or username. (Required.) + Name SCIMUserName `json:"name"` // (Required.) + DisplayName *string `json:"displayName,omitempty"` // The name of the user, suitable for display to end-users. (Optional.) + Emails []*SCIMUserEmail `json:"emails"` // User emails. (Required.) + Schemas []string `json:"schemas,omitempty"` // (Optional.) + ExternalID *string `json:"externalId,omitempty"` // (Optional.) + Groups []string `json:"groups,omitempty"` // (Optional.) + Active *bool `json:"active,omitempty"` // (Optional.) +} + +// SCIMUserName represents SCIM user information. +type SCIMUserName struct { + GivenName string `json:"givenName"` // The first name of the user. (Required.) + FamilyName string `json:"familyName"` // The family name of the user. (Required.) + Formatted *string `json:"formatted,omitempty"` // (Optional.) +} + +//SCIMUserEmail represents SCIM user email. +type SCIMUserEmail struct { + Value string `json:"value"` // (Required.) + Primary *bool `json:"primary,omitempty"` // (Optional.) + Type *string `json:"type,omitempty"` // (Optional.) +} + +// ListSCIMProvisionedIdentitiesOptions represents options for ListSCIMProvisionedIdentities. +// +// Github API docs: https://docs.github.com/en/rest/scim#list-scim-provisioned-identities--parameters +type ListSCIMProvisionedIdentitiesOptions struct { + StartIndex *int `json:"startIndex,omitempty"` // Used for pagination: the index of the first result to return. (Optional.) + Count *int `json:"count,omitempty"` // Used for pagination: the number of results to return. (Optional.) + // Filter results using the equals query parameter operator (eq). + // You can filter results that are equal to id, userName, emails, and external_id. + // For example, to search for an identity with the userName Octocat, you would use this query: ?filter=userName%20eq%20\"Octocat\". + // To filter results for the identity with the email octocat@github.com, you would use this query: ?filter=emails%20eq%20\"octocat@github.com\". + // (Optional.) + Filter *string `json:"filter,omitempty"` +} + +// ListSCIMProvisionedIdentities lists SCIM provisioned identities. +// +// GitHub API docs: https://docs.github.com/en/rest/scim#list-scim-provisioned-identities +func (s *SCIMService) ListSCIMProvisionedIdentities(ctx context.Context, org string, opts *ListSCIMProvisionedIdentitiesOptions) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, err + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// ProvisionAndInviteSCIMUser provisions organization membership for a user, and sends an activation email to the email address. +// +// GitHub API docs: https://docs.github.com/en/rest/scim#provision-and-invite-a-scim-user +func (s *SCIMService) ProvisionAndInviteSCIMUser(ctx context.Context, org string, opts *SCIMUserAttributes) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, err + } + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// GetSCIMProvisioningInfoForUser returns SCIM provisioning information for a user. +// +// GitHub API docs: https://docs.github.com/en/rest/scim#supported-scim-user-attributes +func (s *SCIMService) GetSCIMProvisioningInfoForUser(ctx context.Context, org, scimUserID string) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// UpdateProvisionedOrgMembership updates a provisioned organization membership. +// +// GitHub API docs: https://docs.github.com/en/rest/scim#update-a-provisioned-organization-membership +func (s *SCIMService) UpdateProvisionedOrgMembership(ctx context.Context, org, scimUserID string, opts *SCIMUserAttributes) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + u, err := addOptions(u, opts) + if err != nil { + return nil, err + } + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// UpdateAttributeForSCIMUserOptions represents options for UpdateAttributeForSCIMUser. +// +// GitHub API docs: https://docs.github.com/en/rest/scim#update-an-attribute-for-a-scim-user--parameters +type UpdateAttributeForSCIMUserOptions struct { + Schemas []string `json:"schemas,omitempty"` // (Optional.) + Operations UpdateAttributeForSCIMUserOperations `json:"operations"` // Set of operations to be performed. (Required.) +} + +// UpdateAttributeForSCIMUserOperations represents operations for UpdateAttributeForSCIMUser. +type UpdateAttributeForSCIMUserOperations struct { + Op string `json:"op"` // (Required.) + Path *string `json:"path,omitempty"` // (Optional.) + Value json.RawMessage `json:"value,omitempty"` // (Optional.) +} + +// UpdateAttributeForSCIMUser updates an attribute for an SCIM user. +// +// GitHub API docs: https://docs.github.com/en/rest/scim#update-an-attribute-for-a-scim-user +func (s *SCIMService) UpdateAttributeForSCIMUser(ctx context.Context, org, scimUserID string, opts *UpdateAttributeForSCIMUserOptions) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + u, err := addOptions(u, opts) + if err != nil { + return nil, err + } + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} + +// DeleteSCIMUserFromOrg deletes SCIM user from an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/scim#delete-a-scim-user-from-an-organization +func (s *SCIMService) DeleteSCIMUserFromOrg(ctx context.Context, org, scimUserID string) (*Response, error) { + u := fmt.Sprintf("scim/v2/organizations/%v/Users/%v", org, scimUserID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/search.go b/vendor/github.com/google/go-github/v45/github/search.go new file mode 100644 index 0000000000..344f1bb985 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/search.go @@ -0,0 +1,327 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "strconv" + + qs "github.com/google/go-querystring/query" +) + +// SearchService provides access to the search related functions +// in the GitHub API. +// +// Each method takes a query string defining the search keywords and any search qualifiers. +// For example, when searching issues, the query "gopher is:issue language:go" will search +// for issues containing the word "gopher" in Go repositories. The method call +// opts := &github.SearchOptions{Sort: "created", Order: "asc"} +// cl.Search.Issues(ctx, "gopher is:issue language:go", opts) +// will search for such issues, sorting by creation date in ascending order +// (i.e., oldest first). +// +// If query includes multiple conditions, it MUST NOT include "+" as the condition separator. +// You have to use " " as the separator instead. +// For example, querying with "language:c++" and "leveldb", then query should be +// "language:c++ leveldb" but not "language:c+++leveldb". +// +// GitHub API docs: https://docs.github.com/en/rest/search/ +type SearchService service + +// SearchOptions specifies optional parameters to the SearchService methods. +type SearchOptions struct { + // How to sort the search results. Possible values are: + // - for repositories: stars, fork, updated + // - for commits: author-date, committer-date + // - for code: indexed + // - for issues: comments, created, updated + // - for users: followers, repositories, joined + // + // Default is to sort by best match. + Sort string `url:"sort,omitempty"` + + // Sort order if sort parameter is provided. Possible values are: asc, + // desc. Default is desc. + Order string `url:"order,omitempty"` + + // Whether to retrieve text match metadata with a query + TextMatch bool `url:"-"` + + ListOptions +} + +// Common search parameters. +type searchParameters struct { + Query string + RepositoryID *int64 // Sent if non-nil. +} + +// RepositoriesSearchResult represents the result of a repositories search. +type RepositoriesSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Repositories []*Repository `json:"items,omitempty"` +} + +// Repositories searches repositories via various criteria. +// +// GitHub API docs: https://docs.github.com/en/rest/search#search-repositories +func (s *SearchService) Repositories(ctx context.Context, query string, opts *SearchOptions) (*RepositoriesSearchResult, *Response, error) { + result := new(RepositoriesSearchResult) + resp, err := s.search(ctx, "repositories", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// TopicsSearchResult represents the result of a topics search. +type TopicsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Topics []*TopicResult `json:"items,omitempty"` +} + +type TopicResult struct { + Name *string `json:"name,omitempty"` + DisplayName *string `json:"display_name,omitempty"` + ShortDescription *string `json:"short_description,omitempty"` + Description *string `json:"description,omitempty"` + CreatedBy *string `json:"created_by,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *string `json:"updated_at,omitempty"` + Featured *bool `json:"featured,omitempty"` + Curated *bool `json:"curated,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +// Topics finds topics via various criteria. Results are sorted by best match. +// Please see https://help.github.com/en/articles/searching-topics for more +// information about search qualifiers. +// +// GitHub API docs: https://docs.github.com/en/rest/search#search-topics +func (s *SearchService) Topics(ctx context.Context, query string, opts *SearchOptions) (*TopicsSearchResult, *Response, error) { + result := new(TopicsSearchResult) + resp, err := s.search(ctx, "topics", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// CommitsSearchResult represents the result of a commits search. +type CommitsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Commits []*CommitResult `json:"items,omitempty"` +} + +// CommitResult represents a commit object as returned in commit search endpoint response. +type CommitResult struct { + SHA *string `json:"sha,omitempty"` + Commit *Commit `json:"commit,omitempty"` + Author *User `json:"author,omitempty"` + Committer *User `json:"committer,omitempty"` + Parents []*Commit `json:"parents,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + URL *string `json:"url,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + + Repository *Repository `json:"repository,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +// Commits searches commits via various criteria. +// +// GitHub API docs: https://docs.github.com/en/rest/search#search-commits +func (s *SearchService) Commits(ctx context.Context, query string, opts *SearchOptions) (*CommitsSearchResult, *Response, error) { + result := new(CommitsSearchResult) + resp, err := s.search(ctx, "commits", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// IssuesSearchResult represents the result of an issues search. +type IssuesSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Issues []*Issue `json:"items,omitempty"` +} + +// Issues searches issues via various criteria. +// +// GitHub API docs: https://docs.github.com/en/rest/search#search-issues-and-pull-requests +func (s *SearchService) Issues(ctx context.Context, query string, opts *SearchOptions) (*IssuesSearchResult, *Response, error) { + result := new(IssuesSearchResult) + resp, err := s.search(ctx, "issues", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// UsersSearchResult represents the result of a users search. +type UsersSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Users []*User `json:"items,omitempty"` +} + +// Users searches users via various criteria. +// +// GitHub API docs: https://docs.github.com/en/rest/search#search-users +func (s *SearchService) Users(ctx context.Context, query string, opts *SearchOptions) (*UsersSearchResult, *Response, error) { + result := new(UsersSearchResult) + resp, err := s.search(ctx, "users", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// Match represents a single text match. +type Match struct { + Text *string `json:"text,omitempty"` + Indices []int `json:"indices,omitempty"` +} + +// TextMatch represents a text match for a SearchResult +type TextMatch struct { + ObjectURL *string `json:"object_url,omitempty"` + ObjectType *string `json:"object_type,omitempty"` + Property *string `json:"property,omitempty"` + Fragment *string `json:"fragment,omitempty"` + Matches []*Match `json:"matches,omitempty"` +} + +func (tm TextMatch) String() string { + return Stringify(tm) +} + +// CodeSearchResult represents the result of a code search. +type CodeSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + CodeResults []*CodeResult `json:"items,omitempty"` +} + +// CodeResult represents a single search result. +type CodeResult struct { + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + SHA *string `json:"sha,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + Repository *Repository `json:"repository,omitempty"` + TextMatches []*TextMatch `json:"text_matches,omitempty"` +} + +func (c CodeResult) String() string { + return Stringify(c) +} + +// Code searches code via various criteria. +// +// GitHub API docs: https://docs.github.com/en/rest/search#search-code +func (s *SearchService) Code(ctx context.Context, query string, opts *SearchOptions) (*CodeSearchResult, *Response, error) { + result := new(CodeSearchResult) + resp, err := s.search(ctx, "code", &searchParameters{Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// LabelsSearchResult represents the result of a code search. +type LabelsSearchResult struct { + Total *int `json:"total_count,omitempty"` + IncompleteResults *bool `json:"incomplete_results,omitempty"` + Labels []*LabelResult `json:"items,omitempty"` +} + +// LabelResult represents a single search result. +type LabelResult struct { + ID *int64 `json:"id,omitempty"` + URL *string `json:"url,omitempty"` + Name *string `json:"name,omitempty"` + Color *string `json:"color,omitempty"` + Default *bool `json:"default,omitempty"` + Description *string `json:"description,omitempty"` + Score *float64 `json:"score,omitempty"` +} + +func (l LabelResult) String() string { + return Stringify(l) +} + +// Labels searches labels in the repository with ID repoID via various criteria. +// +// GitHub API docs: https://docs.github.com/en/rest/search#search-labels +func (s *SearchService) Labels(ctx context.Context, repoID int64, query string, opts *SearchOptions) (*LabelsSearchResult, *Response, error) { + result := new(LabelsSearchResult) + resp, err := s.search(ctx, "labels", &searchParameters{RepositoryID: &repoID, Query: query}, opts, result) + if err != nil { + return nil, resp, err + } + + return result, resp, nil +} + +// Helper function that executes search queries against different +// GitHub search types (repositories, commits, code, issues, users, labels) +// +// If searchParameters.Query includes multiple condition, it MUST NOT include "+" as condition separator. +// For example, querying with "language:c++" and "leveldb", then searchParameters.Query should be "language:c++ leveldb" but not "language:c+++leveldb". +func (s *SearchService) search(ctx context.Context, searchType string, parameters *searchParameters, opts *SearchOptions, result interface{}) (*Response, error) { + params, err := qs.Values(opts) + if err != nil { + return nil, err + } + + if parameters.RepositoryID != nil { + params.Set("repository_id", strconv.FormatInt(*parameters.RepositoryID, 10)) + } + params.Set("q", parameters.Query) + u := fmt.Sprintf("search/%s?%s", searchType, params.Encode()) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, err + } + + switch { + case searchType == "commits": + // Accept header for search commits preview endpoint + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeCommitSearchPreview) + case searchType == "topics": + // Accept header for search repositories based on topics preview endpoint + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + case searchType == "repositories": + // Accept header for search repositories based on topics preview endpoint + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeTopicsPreview) + case searchType == "issues": + // Accept header for search issues based on reactions preview endpoint + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeReactionsPreview) + case opts != nil && opts.TextMatch: + // Accept header defaults to "application/vnd.github.v3+json" + // We change it here to fetch back text-match metadata + req.Header.Set("Accept", "application/vnd.github.v3.text-match+json") + } + + return s.client.Do(ctx, req, result) +} diff --git a/vendor/github.com/google/go-github/v45/github/secret_scanning.go b/vendor/github.com/google/go-github/v45/github/secret_scanning.go new file mode 100644 index 0000000000..ec64950a67 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/secret_scanning.go @@ -0,0 +1,232 @@ +// Copyright 2022 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// SecretScanningService handles communication with the secret scanning related +// methods of the GitHub API. +type SecretScanningService service + +// SecretScanningAlert represents a GitHub secret scanning alert. +type SecretScanningAlert struct { + Number *int `json:"number,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + URL *string `json:"url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + LocationsURL *string `json:"locations_url,omitempty"` + State *string `json:"state,omitempty"` + Resolution *string `json:"resolution,omitempty"` + ResolvedAt *Timestamp `json:"resolved_at,omitempty"` + ResolvedBy *User `json:"resolved_by,omitempty"` + SecretType *string `json:"secret_type,omitempty"` + Secret *string `json:"secret,omitempty"` +} + +// SecretScanningAlertLocation represents the location for a secret scanning alert. +type SecretScanningAlertLocation struct { + Type *string `json:"type,omitempty"` + Details *SecretScanningAlertLocationDetails `json:"details,omitempty"` +} + +// SecretScanningAlertLocationDetails represents the location details for a secret scanning alert. +type SecretScanningAlertLocationDetails struct { + Path *string `json:"path,omitempty"` + Startline *int `json:"start_line,omitempty"` + EndLine *int `json:"end_line,omitempty"` + StartColumn *int `json:"start_column,omitempty"` + EndColumn *int `json:"end_column,omitempty"` + BlobSHA *string `json:"blob_sha,omitempty"` + BlobURL *string `json:"blob_url,omitempty"` + CommitSHA *string `json:"commit_sha,omitempty"` + CommitURL *string `json:"commit_url,omitempty"` +} + +// SecretScanningAlertListOptions specifies optional parameters to the SecretScanningService.ListAlertsForEnterprise method. +type SecretScanningAlertListOptions struct { + // State of the secret scanning alerts to list. Set to open or resolved to only list secret scanning alerts in a specific state. + State string `url:"state,omitempty"` + + // A comma-separated list of secret types to return. By default all secret types are returned. + SecretType string `url:"secret_type,omitempty"` + + // A comma-separated list of resolutions. Only secret scanning alerts with one of these resolutions are listed. + // Valid resolutions are false_positive, wont_fix, revoked, pattern_edited, pattern_deleted or used_in_tests. + Resolution string `url:"resolution,omitempty"` + + ListCursorOptions +} + +// SecretScanningAlertUpdateOptions specifies optional parameters to the SecretScanningService.UpdateAlert method. +type SecretScanningAlertUpdateOptions struct { + // Required. Sets the state of the secret scanning alert. Can be either open or resolved. + // You must provide resolution when you set the state to resolved. + State *string `url:"state,omitempty"` + + // A comma-separated list of secret types to return. By default all secret types are returned. + SecretType *string `url:"secret_type,omitempty"` + + // Required when the state is resolved. The reason for resolving the alert. Can be one of false_positive, + // wont_fix, revoked, or used_in_tests. + Resolution *string `url:"resolution,omitempty"` +} + +// Lists secret scanning alerts for eligible repositories in an enterprise, from newest to oldest. +// +// To use this endpoint, you must be a member of the enterprise, and you must use an access token with the repo scope or +// security_events scope. Alerts are only returned for organizations in the enterprise for which you are an organization owner or a security manager. +// +// GitHub API docs: https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-secret-scanning-alerts-for-an-enterprise +func (s *SecretScanningService) ListAlertsForEnterprise(ctx context.Context, enterprise string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("enterprises/%v/secret-scanning/alerts", enterprise) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// Lists secret scanning alerts for eligible repositories in an organization, from newest to oldest. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-secret-scanning-alerts-for-an-organization +func (s *SecretScanningService) ListAlertsForOrg(ctx context.Context, org string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("orgs/%v/secret-scanning/alerts", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// Lists secret scanning alerts for a private repository, from newest to oldest. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-secret-scanning-alerts-for-a-repository +func (s *SecretScanningService) ListAlertsForRepo(ctx context.Context, owner, repo string, opts *SecretScanningAlertListOptions) ([]*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts", owner, repo) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alerts []*SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alerts) + if err != nil { + return nil, resp, err + } + + return alerts, resp, nil +} + +// Gets a single secret scanning alert detected in a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#get-a-secret-scanning-alert +func (s *SecretScanningService) GetAlert(ctx context.Context, owner, repo string, number int64) (*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var alert *SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} + +// Updates the status of a secret scanning alert in a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#update-a-secret-scanning-alert +func (s *SecretScanningService) UpdateAlert(ctx context.Context, owner, repo string, number int64, opts *SecretScanningAlertUpdateOptions) (*SecretScanningAlert, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v", owner, repo, number) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + var alert *SecretScanningAlert + resp, err := s.client.Do(ctx, req, &alert) + if err != nil { + return nil, resp, err + } + + return alert, resp, nil +} + +// Lists all locations for a given secret scanning alert for a private repository. +// +// To use this endpoint, you must be an administrator for the repository or organization, and you must use an access token with +// the repo scope or security_events scope. +// +// GitHub API docs: https://docs.github.com/en/enterprise-server@3.5/rest/secret-scanning#list-locations-for-a-secret-scanning-alert +func (s *SecretScanningService) ListLocationsForAlert(ctx context.Context, owner, repo string, number int64, opts *ListOptions) ([]*SecretScanningAlertLocation, *Response, error) { + u := fmt.Sprintf("repos/%v/%v/secret-scanning/alerts/%v/locations", owner, repo, number) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var locations []*SecretScanningAlertLocation + resp, err := s.client.Do(ctx, req, &locations) + if err != nil { + return nil, resp, err + } + + return locations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/strings.go b/vendor/github.com/google/go-github/v45/github/strings.go new file mode 100644 index 0000000000..5611b96a88 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/strings.go @@ -0,0 +1,96 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "bytes" + "fmt" + "io" + + "reflect" +) + +var timestampType = reflect.TypeOf(Timestamp{}) + +// Stringify attempts to create a reasonable string representation of types in +// the GitHub library. It does things like resolve pointers to their values +// and omits struct fields with nil values. +func Stringify(message interface{}) string { + var buf bytes.Buffer + v := reflect.ValueOf(message) + stringifyValue(&buf, v) + return buf.String() +} + +// stringifyValue was heavily inspired by the goprotobuf library. + +func stringifyValue(w io.Writer, val reflect.Value) { + if val.Kind() == reflect.Ptr && val.IsNil() { + w.Write([]byte("")) + return + } + + v := reflect.Indirect(val) + + switch v.Kind() { + case reflect.String: + fmt.Fprintf(w, `"%s"`, v) + case reflect.Slice: + w.Write([]byte{'['}) + for i := 0; i < v.Len(); i++ { + if i > 0 { + w.Write([]byte{' '}) + } + + stringifyValue(w, v.Index(i)) + } + + w.Write([]byte{']'}) + return + case reflect.Struct: + if v.Type().Name() != "" { + w.Write([]byte(v.Type().String())) + } + + // special handling of Timestamp values + if v.Type() == timestampType { + fmt.Fprintf(w, "{%s}", v.Interface()) + return + } + + w.Write([]byte{'{'}) + + var sep bool + for i := 0; i < v.NumField(); i++ { + fv := v.Field(i) + if fv.Kind() == reflect.Ptr && fv.IsNil() { + continue + } + if fv.Kind() == reflect.Slice && fv.IsNil() { + continue + } + if fv.Kind() == reflect.Map && fv.IsNil() { + continue + } + + if sep { + w.Write([]byte(", ")) + } else { + sep = true + } + + w.Write([]byte(v.Type().Field(i).Name)) + w.Write([]byte{':'}) + stringifyValue(w, fv) + } + + w.Write([]byte{'}'}) + default: + if v.CanInterface() { + fmt.Fprint(w, v.Interface()) + } + } +} diff --git a/vendor/github.com/google/go-github/v45/github/teams.go b/vendor/github.com/google/go-github/v45/github/teams.go new file mode 100644 index 0000000000..77b38dd6dd --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/teams.go @@ -0,0 +1,973 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "net/http" + "strings" + "time" +) + +// TeamsService provides access to the team-related functions +// in the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/ +type TeamsService service + +// Team represents a team within a GitHub organization. Teams are used to +// manage access to an organization's repositories. +type Team struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + URL *string `json:"url,omitempty"` + Slug *string `json:"slug,omitempty"` + + // Permission specifies the default permission for repositories owned by the team. + Permission *string `json:"permission,omitempty"` + + // Permissions identifies the permissions that a team has on a given + // repository. This is only populated when calling Repositories.ListTeams. + Permissions map[string]bool `json:"permissions,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + + MembersCount *int `json:"members_count,omitempty"` + ReposCount *int `json:"repos_count,omitempty"` + Organization *Organization `json:"organization,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + MembersURL *string `json:"members_url,omitempty"` + RepositoriesURL *string `json:"repositories_url,omitempty"` + Parent *Team `json:"parent,omitempty"` + + // LDAPDN is only available in GitHub Enterprise and when the team + // membership is synchronized with LDAP. + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +func (t Team) String() string { + return Stringify(t) +} + +// Invitation represents a team member's invitation status. +type Invitation struct { + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Login *string `json:"login,omitempty"` + Email *string `json:"email,omitempty"` + // Role can be one of the values - 'direct_member', 'admin', 'billing_manager', 'hiring_manager', or 'reinstate'. + Role *string `json:"role,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + Inviter *User `json:"inviter,omitempty"` + TeamCount *int `json:"team_count,omitempty"` + InvitationTeamURL *string `json:"invitation_team_url,omitempty"` + FailedAt *Timestamp `json:"failed_at,omitempty"` + FailedReason *string `json:"failed_reason,omitempty"` +} + +func (i Invitation) String() string { + return Stringify(i) +} + +// ListTeams lists all of the teams for an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-teams +func (s *TeamsService) ListTeams(ctx context.Context, org string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// GetTeamByID fetches a team, given a specified organization ID, by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#get-a-team-by-name +func (s *TeamsService) GetTeamByID(ctx context.Context, orgID, teamID int64) (*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// GetTeamBySlug fetches a team, given a specified organization name, by slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#get-a-team-by-name +func (s *TeamsService) GetTeamBySlug(ctx context.Context, org, slug string) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// NewTeam represents a team to be created or modified. +type NewTeam struct { + Name string `json:"name"` // Name of the team. (Required.) + Description *string `json:"description,omitempty"` + Maintainers []string `json:"maintainers,omitempty"` + RepoNames []string `json:"repo_names,omitempty"` + ParentTeamID *int64 `json:"parent_team_id,omitempty"` + + // Deprecated: Permission is deprecated when creating or editing a team in an org + // using the new GitHub permission model. It no longer identifies the + // permission a team has on its repos, but only specifies the default + // permission a repo is initially added with. Avoid confusion by + // specifying a permission value when calling AddTeamRepo. + Permission *string `json:"permission,omitempty"` + + // Privacy identifies the level of privacy this team should have. + // Possible values are: + // secret - only visible to organization owners and members of this team + // closed - visible to all members of this organization + // Default is "secret". + Privacy *string `json:"privacy,omitempty"` + + // LDAPDN may be used in GitHub Enterprise when the team membership + // is synchronized with LDAP. + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +func (s NewTeam) String() string { + return Stringify(s) +} + +// CreateTeam creates a new team within an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#create-a-team +func (s *TeamsService) CreateTeam(ctx context.Context, org string, team NewTeam) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams", org) + req, err := s.client.NewRequest("POST", u, team) + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// newTeamNoParent is the same as NewTeam but ensures that the +// "parent_team_id" field will be null. It is for internal use +// only and should not be exported. +type newTeamNoParent struct { + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Maintainers []string `json:"maintainers,omitempty"` + RepoNames []string `json:"repo_names,omitempty"` + ParentTeamID *int64 `json:"parent_team_id"` // This will be "null" + Privacy *string `json:"privacy,omitempty"` + LDAPDN *string `json:"ldap_dn,omitempty"` +} + +// copyNewTeamWithoutParent is used to set the "parent_team_id" +// field to "null" after copying the other fields from a NewTeam. +// It is for internal use only and should not be exported. +func copyNewTeamWithoutParent(team *NewTeam) *newTeamNoParent { + return &newTeamNoParent{ + Name: team.Name, + Description: team.Description, + Maintainers: team.Maintainers, + RepoNames: team.RepoNames, + Privacy: team.Privacy, + LDAPDN: team.LDAPDN, + } +} + +// EditTeamByID edits a team, given an organization ID, selected by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#update-a-team +func (s *TeamsService) EditTeamByID(ctx context.Context, orgID, teamID int64, team NewTeam, removeParent bool) (*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + + var req *http.Request + var err error + if removeParent { + teamRemoveParent := copyNewTeamWithoutParent(&team) + req, err = s.client.NewRequest("PATCH", u, teamRemoveParent) + } else { + req, err = s.client.NewRequest("PATCH", u, team) + } + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// EditTeamBySlug edits a team, given an organization name, by slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#update-a-team +func (s *TeamsService) EditTeamBySlug(ctx context.Context, org, slug string, team NewTeam, removeParent bool) (*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + + var req *http.Request + var err error + if removeParent { + teamRemoveParent := copyNewTeamWithoutParent(&team) + req, err = s.client.NewRequest("PATCH", u, teamRemoveParent) + } else { + req, err = s.client.NewRequest("PATCH", u, team) + } + if err != nil { + return nil, nil, err + } + + t := new(Team) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// DeleteTeamByID deletes a team referenced by ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#delete-a-team +func (s *TeamsService) DeleteTeamByID(ctx context.Context, orgID, teamID int64) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v", orgID, teamID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteTeamBySlug deletes a team reference by slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#delete-a-team +func (s *TeamsService) DeleteTeamBySlug(ctx context.Context, org, slug string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v", org, slug) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListChildTeamsByParentID lists child teams for a parent team given parent ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-child-teams +func (s *TeamsService) ListChildTeamsByParentID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/teams", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListChildTeamsByParentSlug lists child teams for a parent team given parent slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-child-teams +func (s *TeamsService) ListChildTeamsByParentSlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Team, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/teams", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListTeamReposByID lists the repositories given a team ID that the specified team has access to. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-team-repositories +func (s *TeamsService) ListTeamReposByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + headers := []string{mediaTypeTopicsPreview} + req.Header.Set("Accept", strings.Join(headers, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// ListTeamReposBySlug lists the repositories given a team slug that the specified team has access to. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-team-repositories +func (s *TeamsService) ListTeamReposBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when topics API fully launches. + headers := []string{mediaTypeTopicsPreview} + req.Header.Set("Accept", strings.Join(headers, ", ")) + + var repos []*Repository + resp, err := s.client.Do(ctx, req, &repos) + if err != nil { + return nil, resp, err + } + + return repos, resp, nil +} + +// IsTeamRepoByID checks if a team, given its ID, manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-repository +func (s *TeamsService) IsTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + headers := []string{mediaTypeOrgPermissionRepo} + req.Header.Set("Accept", strings.Join(headers, ", ")) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// IsTeamRepoBySlug checks if a team, given its slug, manages the specified repository. If the +// repository is managed by team, a Repository is returned which includes the +// permissions team has for that repo. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-repository +func (s *TeamsService) IsTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Repository, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + headers := []string{mediaTypeOrgPermissionRepo} + req.Header.Set("Accept", strings.Join(headers, ", ")) + + repository := new(Repository) + resp, err := s.client.Do(ctx, req, repository) + if err != nil { + return nil, resp, err + } + + return repository, resp, nil +} + +// TeamAddTeamRepoOptions specifies the optional parameters to the +// TeamsService.AddTeamRepo method. +type TeamAddTeamRepoOptions struct { + // Permission specifies the permission to grant the team on this repository. + // Possible values are: + // pull - team members can pull, but not push to or administer this repository + // push - team members can pull and push, but not administer this repository + // admin - team members can pull, push and administer this repository + // maintain - team members can manage the repository without access to sensitive or destructive actions. + // triage - team members can proactively manage issues and pull requests without write access. + // + // If not specified, the team's permission attribute will be used. + Permission string `json:"permission,omitempty"` +} + +// AddTeamRepoByID adds a repository to be managed by the specified team given the team ID. +// The specified repository must be owned by the organization to which the team +// belongs, or a direct fork of a repository owned by the organization. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions +func (s *TeamsService) AddTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// AddTeamRepoBySlug adds a repository to be managed by the specified team given the team slug. +// The specified repository must be owned by the organization to which the team +// belongs, or a direct fork of a repository owned by the organization. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#add-or-update-team-repository-permissions +func (s *TeamsService) AddTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string, opts *TeamAddTeamRepoOptions) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamRepoByID removes a repository from being managed by the specified +// team given the team ID. Note that this does not delete the repository, it +// just removes it from the team. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#remove-a-repository-from-a-team +func (s *TeamsService) RemoveTeamRepoByID(ctx context.Context, orgID, teamID int64, owner, repo string) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/repos/%v/%v", orgID, teamID, owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamRepoBySlug removes a repository from being managed by the specified +// team given the team slug. Note that this does not delete the repository, it +// just removes it from the team. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#remove-a-repository-from-a-team +func (s *TeamsService) RemoveTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/repos/%v/%v", org, slug, owner, repo) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListUserTeams lists a user's teams +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-teams-for-the-authenticated-user +func (s *TeamsService) ListUserTeams(ctx context.Context, opts *ListOptions) ([]*Team, *Response, error) { + u := "user/teams" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teams []*Team + resp, err := s.client.Do(ctx, req, &teams) + if err != nil { + return nil, resp, err + } + + return teams, resp, nil +} + +// ListTeamProjectsByID lists the organization projects for a team given the team ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-team-projects +func (s *TeamsService) ListTeamProjectsByID(ctx context.Context, orgID, teamID int64) ([]*Project, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects", orgID, teamID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeProjectsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var projects []*Project + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ListTeamProjectsBySlug lists the organization projects for a team given the team slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#list-team-projects +func (s *TeamsService) ListTeamProjectsBySlug(ctx context.Context, org, slug string) ([]*Project, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects", org, slug) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeProjectsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + var projects []*Project + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ReviewTeamProjectsByID checks whether a team, given its ID, has read, write, or admin +// permissions for an organization project. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-project +func (s *TeamsService) ReviewTeamProjectsByID(ctx context.Context, orgID, teamID, projectID int64) (*Project, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeProjectsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + projects := &Project{} + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// ReviewTeamProjectsBySlug checks whether a team, given its slug, has read, write, or admin +// permissions for an organization project. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#check-team-permissions-for-a-project +func (s *TeamsService) ReviewTeamProjectsBySlug(ctx context.Context, org, slug string, projectID int64) (*Project, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeProjectsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + projects := &Project{} + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// TeamProjectOptions specifies the optional parameters to the +// TeamsService.AddTeamProject method. +type TeamProjectOptions struct { + // Permission specifies the permission to grant to the team for this project. + // Possible values are: + // "read" - team members can read, but not write to or administer this project. + // "write" - team members can read and write, but not administer this project. + // "admin" - team members can read, write and administer this project. + // + Permission *string `json:"permission,omitempty"` +} + +// AddTeamProjectByID adds an organization project to a team given the team ID. +// To add a project to a team or update the team's permission on a project, the +// authenticated user must have admin permissions for the project. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#add-or-update-team-project-permissions +func (s *TeamsService) AddTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64, opts *TeamProjectOptions) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeProjectsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + return s.client.Do(ctx, req, nil) +} + +// AddTeamProjectBySlug adds an organization project to a team given the team slug. +// To add a project to a team or update the team's permission on a project, the +// authenticated user must have admin permissions for the project. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#add-or-update-team-project-permissions +func (s *TeamsService) AddTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64, opts *TeamProjectOptions) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeProjectsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamProjectByID removes an organization project from a team given team ID. +// An organization owner or a team maintainer can remove any project from the team. +// To remove a project from a team as an organization member, the authenticated user +// must have "read" access to both the team and project, or "admin" access to the team +// or project. +// Note: This endpoint removes the project from the team, but does not delete it. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#remove-a-project-from-a-team +func (s *TeamsService) RemoveTeamProjectByID(ctx context.Context, orgID, teamID, projectID int64) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/projects/%v", orgID, teamID, projectID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeProjectsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamProjectBySlug removes an organization project from a team given team slug. +// An organization owner or a team maintainer can remove any project from the team. +// To remove a project from a team as an organization member, the authenticated user +// must have "read" access to both the team and project, or "admin" access to the team +// or project. +// Note: This endpoint removes the project from the team, but does not delete it. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/teams#remove-a-project-from-a-team +func (s *TeamsService) RemoveTeamProjectBySlug(ctx context.Context, org, slug string, projectID int64) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/projects/%v", org, slug, projectID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + acceptHeaders := []string{mediaTypeProjectsPreview} + req.Header.Set("Accept", strings.Join(acceptHeaders, ", ")) + + return s.client.Do(ctx, req, nil) +} + +// IDPGroupList represents a list of external identity provider (IDP) groups. +type IDPGroupList struct { + Groups []*IDPGroup `json:"groups"` +} + +// IDPGroup represents an external identity provider (IDP) group. +type IDPGroup struct { + GroupID *string `json:"group_id,omitempty"` + GroupName *string `json:"group_name,omitempty"` + GroupDescription *string `json:"group_description,omitempty"` +} + +// ListIDPGroupsInOrganization lists IDP groups available in an organization. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#list-idp-groups-for-an-organization +func (s *TeamsService) ListIDPGroupsInOrganization(ctx context.Context, org string, opts *ListCursorOptions) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/team-sync/groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ListIDPGroupsForTeamByID lists IDP groups connected to a team on GitHub +// given organization and team IDs. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#list-idp-groups-for-a-team +func (s *TeamsService) ListIDPGroupsForTeamByID(ctx context.Context, orgID, teamID int64) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ListIDPGroupsForTeamBySlug lists IDP groups connected to a team on GitHub +// given organization name and team slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#list-idp-groups-for-a-team +func (s *TeamsService) ListIDPGroupsForTeamBySlug(ctx context.Context, org, slug string) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// CreateOrUpdateIDPGroupConnectionsByID creates, updates, or removes a connection +// between a team and an IDP group given organization and team IDs. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#create-or-update-idp-group-connections +func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsByID(ctx context.Context, orgID, teamID int64, opts IDPGroupList) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/team-sync/group-mappings", orgID, teamID) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// CreateOrUpdateIDPGroupConnectionsBySlug creates, updates, or removes a connection +// between a team and an IDP group given organization name and team slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/team-sync#create-or-update-idp-group-connections +func (s *TeamsService) CreateOrUpdateIDPGroupConnectionsBySlug(ctx context.Context, org, slug string, opts IDPGroupList) (*IDPGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/team-sync/group-mappings", org, slug) + + req, err := s.client.NewRequest("PATCH", u, opts) + if err != nil { + return nil, nil, err + } + + groups := new(IDPGroupList) + resp, err := s.client.Do(ctx, req, groups) + if err != nil { + return nil, resp, err + } + + return groups, resp, nil +} + +// ExternalGroupMember represents a member of an external group. +type ExternalGroupMember struct { + MemberID *int64 `json:"member_id,omitempty"` + MemberLogin *string `json:"member_login,omitempty"` + MemberName *string `json:"member_name,omitempty"` + MemberEmail *string `json:"member_email,omitempty"` +} + +// ExternalGroupTeam represents a team connected to an external group. +type ExternalGroupTeam struct { + TeamID *int64 `json:"team_id,omitempty"` + TeamName *string `json:"team_name,omitempty"` +} + +// ExternalGroup represents an external group. +type ExternalGroup struct { + GroupID *int64 `json:"group_id,omitempty"` + GroupName *string `json:"group_name,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + Teams []*ExternalGroupTeam `json:"teams,omitempty"` + Members []*ExternalGroupMember `json:"members,omitempty"` +} + +// ExternalGroupList represents a list of external groups. +type ExternalGroupList struct { + Groups []*ExternalGroup `json:"groups"` +} + +// GetExternalGroup fetches an external group. +// +// GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#get-an-external-group +func (s *TeamsService) GetExternalGroup(ctx context.Context, org string, groupID int64) (*ExternalGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/external-group/%v", org, groupID) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + externalGroup := new(ExternalGroup) + resp, err := s.client.Do(ctx, req, externalGroup) + if err != nil { + return nil, resp, err + } + + return externalGroup, resp, nil +} + +// ListExternalGroupsOptions specifies the optional parameters to the +// TeamsService.ListExternalGroups method. +type ListExternalGroupsOptions struct { + DisplayName *string `url:"display_name,omitempty"` + + ListOptions +} + +// ListExternalGroups lists external groups connected to a team on GitHub. +// +// GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#list-external-groups-in-an-organization +func (s *TeamsService) ListExternalGroups(ctx context.Context, org string, opts *ListExternalGroupsOptions) (*ExternalGroupList, *Response, error) { + u := fmt.Sprintf("orgs/%v/external-groups", org) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + externalGroups := new(ExternalGroupList) + resp, err := s.client.Do(ctx, req, externalGroups) + if err != nil { + return nil, resp, err + } + + return externalGroups, resp, nil +} + +// UpdateConnectedExternalGroup updates the connection between an external group and a team. +// +// GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#update-the-connection-between-an-external-group-and-a-team +func (s *TeamsService) UpdateConnectedExternalGroup(ctx context.Context, org, slug string, eg *ExternalGroup) (*ExternalGroup, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) + + req, err := s.client.NewRequest("PATCH", u, eg) + if err != nil { + return nil, nil, err + } + + externalGroup := new(ExternalGroup) + resp, err := s.client.Do(ctx, req, externalGroup) + if err != nil { + return nil, resp, err + } + + return externalGroup, resp, nil +} + +// RemoveConnectedExternalGroup removes the connection between an external group and a team. +// +// GitHub API docs: https://docs.github.com/en/enterprise-cloud@latest/rest/teams/external-groups#remove-the-connection-between-an-external-group-and-a-team +func (s *TeamsService) RemoveConnectedExternalGroup(ctx context.Context, org, slug string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/external-groups", org, slug) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/teams_discussion_comments.go b/vendor/github.com/google/go-github/v45/github/teams_discussion_comments.go new file mode 100644 index 0000000000..f3a1cc4dc0 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/teams_discussion_comments.go @@ -0,0 +1,242 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// DiscussionComment represents a GitHub dicussion in a team. +type DiscussionComment struct { + Author *User `json:"author,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + BodyVersion *string `json:"body_version,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` + DiscussionURL *string `json:"discussion_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` +} + +func (c DiscussionComment) String() string { + return Stringify(c) +} + +// DiscussionCommentListOptions specifies optional parameters to the +// TeamServices.ListComments method. +type DiscussionCommentListOptions struct { + // Sorts the discussion comments by the date they were created. + // Accepted values are asc and desc. Default is desc. + Direction string `url:"direction,omitempty"` + ListOptions +} + +// ListCommentsByID lists all comments on a team discussion by team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#list-discussion-comments +func (s *TeamsService) ListCommentsByID(ctx context.Context, orgID, teamID int64, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments", orgID, teamID, discussionNumber) + u, err := addOptions(u, options) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*DiscussionComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// ListCommentsBySlug lists all comments on a team discussion by team slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#list-discussion-comments +func (s *TeamsService) ListCommentsBySlug(ctx context.Context, org, slug string, discussionNumber int, options *DiscussionCommentListOptions) ([]*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discussionNumber) + u, err := addOptions(u, options) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var comments []*DiscussionComment + resp, err := s.client.Do(ctx, req, &comments) + if err != nil { + return nil, resp, err + } + + return comments, resp, nil +} + +// GetCommentByID gets a specific comment on a team discussion by team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#get-a-discussion-comment +func (s *TeamsService) GetCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// GetCommentBySlug gets a specific comment on a team discussion by team slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#get-a-discussion-comment +func (s *TeamsService) GetCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// CreateCommentByID creates a new comment on a team discussion by team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#create-a-discussion-comment +func (s *TeamsService) CreateCommentByID(ctx context.Context, orgID, teamID int64, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments", orgID, teamID, discsusionNumber) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// CreateCommentBySlug creates a new comment on a team discussion by team slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#create-a-discussion-comment +func (s *TeamsService) CreateCommentBySlug(ctx context.Context, org, slug string, discsusionNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments", org, slug, discsusionNumber) + req, err := s.client.NewRequest("POST", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// EditCommentByID edits the body text of a discussion comment by team ID. +// Authenticated user must grant write:discussion scope. +// User is allowed to edit body of a comment only. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#update-a-discussion-comment +func (s *TeamsService) EditCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// EditCommentBySlug edits the body text of a discussion comment by team slug. +// Authenticated user must grant write:discussion scope. +// User is allowed to edit body of a comment only. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#update-a-discussion-comment +func (s *TeamsService) EditCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int, comment DiscussionComment) (*DiscussionComment, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + req, err := s.client.NewRequest("PATCH", u, comment) + if err != nil { + return nil, nil, err + } + + discussionComment := &DiscussionComment{} + resp, err := s.client.Do(ctx, req, discussionComment) + if err != nil { + return nil, resp, err + } + + return discussionComment, resp, nil +} + +// DeleteCommentByID deletes a comment on a team discussion by team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#delete-a-discussion-comment +func (s *TeamsService) DeleteCommentByID(ctx context.Context, orgID, teamID int64, discussionNumber, commentNumber int) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v/comments/%v", orgID, teamID, discussionNumber, commentNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteCommentBySlug deletes a comment on a team discussion by team slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussion-comments#delete-a-discussion-comment +func (s *TeamsService) DeleteCommentBySlug(ctx context.Context, org, slug string, discussionNumber, commentNumber int) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v/comments/%v", org, slug, discussionNumber, commentNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/teams_discussions.go b/vendor/github.com/google/go-github/v45/github/teams_discussions.go new file mode 100644 index 0000000000..69a3ebd51f --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/teams_discussions.go @@ -0,0 +1,247 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TeamDiscussion represents a GitHub dicussion in a team. +type TeamDiscussion struct { + Author *User `json:"author,omitempty"` + Body *string `json:"body,omitempty"` + BodyHTML *string `json:"body_html,omitempty"` + BodyVersion *string `json:"body_version,omitempty"` + CommentsCount *int `json:"comments_count,omitempty"` + CommentsURL *string `json:"comments_url,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + LastEditedAt *Timestamp `json:"last_edited_at,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + NodeID *string `json:"node_id,omitempty"` + Number *int `json:"number,omitempty"` + Pinned *bool `json:"pinned,omitempty"` + Private *bool `json:"private,omitempty"` + TeamURL *string `json:"team_url,omitempty"` + Title *string `json:"title,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + URL *string `json:"url,omitempty"` + Reactions *Reactions `json:"reactions,omitempty"` +} + +func (d TeamDiscussion) String() string { + return Stringify(d) +} + +// DiscussionListOptions specifies optional parameters to the +// TeamServices.ListDiscussions method. +type DiscussionListOptions struct { + // Sorts the discussion by the date they were created. + // Accepted values are asc and desc. Default is desc. + Direction string `url:"direction,omitempty"` + + ListOptions +} + +// ListDiscussionsByID lists all discussions on team's page given Organization and Team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#list-discussions +func (s *TeamsService) ListDiscussionsByID(ctx context.Context, orgID, teamID int64, opts *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teamDiscussions []*TeamDiscussion + resp, err := s.client.Do(ctx, req, &teamDiscussions) + if err != nil { + return nil, resp, err + } + + return teamDiscussions, resp, nil +} + +// ListDiscussionsBySlug lists all discussions on team's page given Organization name and Team's slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#list-discussions +func (s *TeamsService) ListDiscussionsBySlug(ctx context.Context, org, slug string, opts *DiscussionListOptions) ([]*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var teamDiscussions []*TeamDiscussion + resp, err := s.client.Do(ctx, req, &teamDiscussions) + if err != nil { + return nil, resp, err + } + + return teamDiscussions, resp, nil +} + +// GetDiscussionByID gets a specific discussion on a team's page given Organization and Team ID. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#get-a-discussion +func (s *TeamsService) GetDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// GetDiscussionBySlug gets a specific discussion on a team's page given Organization name and Team's slug. +// Authenticated user must grant read:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#get-a-discussion +func (s *TeamsService) GetDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// CreateDiscussionByID creates a new discussion post on a team's page given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#create-a-discussion +func (s *TeamsService) CreateDiscussionByID(ctx context.Context, orgID, teamID int64, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions", orgID, teamID) + req, err := s.client.NewRequest("POST", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// CreateDiscussionBySlug creates a new discussion post on a team's page given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#create-a-discussion +func (s *TeamsService) CreateDiscussionBySlug(ctx context.Context, org, slug string, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions", org, slug) + req, err := s.client.NewRequest("POST", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// EditDiscussionByID edits the title and body text of a discussion post given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// User is allowed to change Title and Body of a discussion only. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#update-a-discussion +func (s *TeamsService) EditDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("PATCH", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// EditDiscussionBySlug edits the title and body text of a discussion post given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// User is allowed to change Title and Body of a discussion only. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#update-a-discussion +func (s *TeamsService) EditDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int, discussion TeamDiscussion) (*TeamDiscussion, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("PATCH", u, discussion) + if err != nil { + return nil, nil, err + } + + teamDiscussion := &TeamDiscussion{} + resp, err := s.client.Do(ctx, req, teamDiscussion) + if err != nil { + return nil, resp, err + } + + return teamDiscussion, resp, nil +} + +// DeleteDiscussionByID deletes a discussion from team's page given Organization and Team ID. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#delete-a-discussion +func (s *TeamsService) DeleteDiscussionByID(ctx context.Context, orgID, teamID int64, discussionNumber int) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/discussions/%v", orgID, teamID, discussionNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeleteDiscussionBySlug deletes a discussion from team's page given Organization name and Team's slug. +// Authenticated user must grant write:discussion scope. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/discussions#delete-a-discussion +func (s *TeamsService) DeleteDiscussionBySlug(ctx context.Context, org, slug string, discussionNumber int) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/discussions/%v", org, slug, discussionNumber) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/teams_members.go b/vendor/github.com/google/go-github/v45/github/teams_members.go new file mode 100644 index 0000000000..58cb79744e --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/teams_members.go @@ -0,0 +1,243 @@ +// Copyright 2018 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// TeamListTeamMembersOptions specifies the optional parameters to the +// TeamsService.ListTeamMembers method. +type TeamListTeamMembersOptions struct { + // Role filters members returned by their role in the team. Possible + // values are "all", "member", "maintainer". Default is "all". + Role string `url:"role,omitempty"` + + ListOptions +} + +// ListTeamMembersByID lists all of the users who are members of a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#list-team-members +func (s *TeamsService) ListTeamMembersByID(ctx context.Context, orgID, teamID int64, opts *TeamListTeamMembersOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/members", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// ListTeamMembersBySlug lists all of the users who are members of a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#list-team-members +func (s *TeamsService) ListTeamMembersBySlug(ctx context.Context, org, slug string, opts *TeamListTeamMembersOptions) ([]*User, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/members", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var members []*User + resp, err := s.client.Do(ctx, req, &members) + if err != nil { + return nil, resp, err + } + + return members, resp, nil +} + +// GetTeamMembershipByID returns the membership status for a user in a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#list-team-members +func (s *TeamsService) GetTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string) (*Membership, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// GetTeamMembershipBySlug returns the membership status for a user in a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#get-team-membership-for-a-user +func (s *TeamsService) GetTeamMembershipBySlug(ctx context.Context, org, slug, user string) (*Membership, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// TeamAddTeamMembershipOptions specifies the optional +// parameters to the TeamsService.AddTeamMembership method. +type TeamAddTeamMembershipOptions struct { + // Role specifies the role the user should have in the team. Possible + // values are: + // member - a normal member of the team + // maintainer - a team maintainer. Able to add/remove other team + // members, promote other team members to team + // maintainer, and edit the team’s name and description + // + // Default value is "member". + Role string `json:"role,omitempty"` +} + +// AddTeamMembershipByID adds or invites a user to a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#add-or-update-team-membership-for-a-user +func (s *TeamsService) AddTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string, opts *TeamAddTeamMembershipOptions) (*Membership, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// AddTeamMembershipBySlug adds or invites a user to a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#add-or-update-team-membership-for-a-user +func (s *TeamsService) AddTeamMembershipBySlug(ctx context.Context, org, slug, user string, opts *TeamAddTeamMembershipOptions) (*Membership, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, nil, err + } + + t := new(Membership) + resp, err := s.client.Do(ctx, req, t) + if err != nil { + return nil, resp, err + } + + return t, resp, nil +} + +// RemoveTeamMembershipByID removes a user from a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#remove-team-membership-for-a-user +func (s *TeamsService) RemoveTeamMembershipByID(ctx context.Context, orgID, teamID int64, user string) (*Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/memberships/%v", orgID, teamID, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// RemoveTeamMembershipBySlug removes a user from a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#remove-team-membership-for-a-user +func (s *TeamsService) RemoveTeamMembershipBySlug(ctx context.Context, org, slug, user string) (*Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/memberships/%v", org, slug, user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// ListPendingTeamInvitationsByID gets pending invitation list of a team, given a specified +// organization ID, by team ID. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#list-pending-team-invitations +func (s *TeamsService) ListPendingTeamInvitationsByID(ctx context.Context, orgID, teamID int64, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("organizations/%v/team/%v/invitations", orgID, teamID) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} + +// ListPendingTeamInvitationsBySlug get pending invitation list of a team, given a specified +// organization name, by team slug. +// +// GitHub API docs: https://docs.github.com/en/rest/teams/members#list-pending-team-invitations +func (s *TeamsService) ListPendingTeamInvitationsBySlug(ctx context.Context, org, slug string, opts *ListOptions) ([]*Invitation, *Response, error) { + u := fmt.Sprintf("orgs/%v/teams/%v/invitations", org, slug) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pendingInvitations []*Invitation + resp, err := s.client.Do(ctx, req, &pendingInvitations) + if err != nil { + return nil, resp, err + } + + return pendingInvitations, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/timestamp.go b/vendor/github.com/google/go-github/v45/github/timestamp.go new file mode 100644 index 0000000000..1061a55e68 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/timestamp.go @@ -0,0 +1,44 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "strconv" + "time" +) + +// Timestamp represents a time that can be unmarshalled from a JSON string +// formatted as either an RFC3339 or Unix timestamp. This is necessary for some +// fields since the GitHub API is inconsistent in how it represents times. All +// exported methods of time.Time can be called on Timestamp. +type Timestamp struct { + time.Time +} + +func (t Timestamp) String() string { + return t.Time.String() +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +// Time is expected in RFC3339 or Unix format. +func (t *Timestamp) UnmarshalJSON(data []byte) (err error) { + str := string(data) + i, err := strconv.ParseInt(str, 10, 64) + if err == nil { + t.Time = time.Unix(i, 0) + if t.Time.Year() > 3000 { + t.Time = time.Unix(0, i*1e6) + } + } else { + t.Time, err = time.Parse(`"`+time.RFC3339+`"`, str) + } + return +} + +// Equal reports whether t and u are equal based on time.Equal +func (t Timestamp) Equal(u Timestamp) bool { + return t.Time.Equal(u.Time) +} diff --git a/vendor/github.com/google/go-github/v45/github/users.go b/vendor/github.com/google/go-github/v45/github/users.go new file mode 100644 index 0000000000..e694e05416 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users.go @@ -0,0 +1,276 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// UsersService handles communication with the user related +// methods of the GitHub API. +// +// GitHub API docs: https://docs.github.com/en/rest/users/ +type UsersService service + +// User represents a GitHub user. +type User struct { + Login *string `json:"login,omitempty"` + ID *int64 `json:"id,omitempty"` + NodeID *string `json:"node_id,omitempty"` + AvatarURL *string `json:"avatar_url,omitempty"` + HTMLURL *string `json:"html_url,omitempty"` + GravatarID *string `json:"gravatar_id,omitempty"` + Name *string `json:"name,omitempty"` + Company *string `json:"company,omitempty"` + Blog *string `json:"blog,omitempty"` + Location *string `json:"location,omitempty"` + Email *string `json:"email,omitempty"` + Hireable *bool `json:"hireable,omitempty"` + Bio *string `json:"bio,omitempty"` + TwitterUsername *string `json:"twitter_username,omitempty"` + PublicRepos *int `json:"public_repos,omitempty"` + PublicGists *int `json:"public_gists,omitempty"` + Followers *int `json:"followers,omitempty"` + Following *int `json:"following,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` + UpdatedAt *Timestamp `json:"updated_at,omitempty"` + SuspendedAt *Timestamp `json:"suspended_at,omitempty"` + Type *string `json:"type,omitempty"` + SiteAdmin *bool `json:"site_admin,omitempty"` + TotalPrivateRepos *int `json:"total_private_repos,omitempty"` + OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"` + PrivateGists *int `json:"private_gists,omitempty"` + DiskUsage *int `json:"disk_usage,omitempty"` + Collaborators *int `json:"collaborators,omitempty"` + TwoFactorAuthentication *bool `json:"two_factor_authentication,omitempty"` + Plan *Plan `json:"plan,omitempty"` + LdapDn *string `json:"ldap_dn,omitempty"` + + // API URLs + URL *string `json:"url,omitempty"` + EventsURL *string `json:"events_url,omitempty"` + FollowingURL *string `json:"following_url,omitempty"` + FollowersURL *string `json:"followers_url,omitempty"` + GistsURL *string `json:"gists_url,omitempty"` + OrganizationsURL *string `json:"organizations_url,omitempty"` + ReceivedEventsURL *string `json:"received_events_url,omitempty"` + ReposURL *string `json:"repos_url,omitempty"` + StarredURL *string `json:"starred_url,omitempty"` + SubscriptionsURL *string `json:"subscriptions_url,omitempty"` + + // TextMatches is only populated from search results that request text matches + // See: search.go and https://docs.github.com/en/rest/search/#text-match-metadata + TextMatches []*TextMatch `json:"text_matches,omitempty"` + + // Permissions identifies the permissions that a user has on a given + // repository. This is only populated when calling Repositories.ListCollaborators. + Permissions map[string]bool `json:"permissions,omitempty"` +} + +func (u User) String() string { + return Stringify(u) +} + +// Get fetches a user. Passing the empty string will fetch the authenticated +// user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/users#get-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/users/users#get-a-user +func (s *UsersService) Get(ctx context.Context, user string) (*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v", user) + } else { + u = "user" + } + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + uResp := new(User) + resp, err := s.client.Do(ctx, req, uResp) + if err != nil { + return nil, resp, err + } + + return uResp, resp, nil +} + +// GetByID fetches a user. +// +// Note: GetByID uses the undocumented GitHub API endpoint /user/:id. +func (s *UsersService) GetByID(ctx context.Context, id int64) (*User, *Response, error) { + u := fmt.Sprintf("user/%d", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + user := new(User) + resp, err := s.client.Do(ctx, req, user) + if err != nil { + return nil, resp, err + } + + return user, resp, nil +} + +// Edit the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/users#update-the-authenticated-user +func (s *UsersService) Edit(ctx context.Context, user *User) (*User, *Response, error) { + u := "user" + req, err := s.client.NewRequest("PATCH", u, user) + if err != nil { + return nil, nil, err + } + + uResp := new(User) + resp, err := s.client.Do(ctx, req, uResp) + if err != nil { + return nil, resp, err + } + + return uResp, resp, nil +} + +// HovercardOptions specifies optional parameters to the UsersService.GetHovercard +// method. +type HovercardOptions struct { + // SubjectType specifies the additional information to be received about the hovercard. + // Possible values are: organization, repository, issue, pull_request. (Required when using subject_id.) + SubjectType string `url:"subject_type"` + + // SubjectID specifies the ID for the SubjectType. (Required when using subject_type.) + SubjectID string `url:"subject_id"` +} + +// Hovercard represents hovercard information about a user. +type Hovercard struct { + Contexts []*UserContext `json:"contexts,omitempty"` +} + +// UserContext represents the contextual information about user. +type UserContext struct { + Message *string `json:"message,omitempty"` + Octicon *string `json:"octicon,omitempty"` +} + +// GetHovercard fetches contextual information about user. It requires authentication +// via Basic Auth or via OAuth with the repo scope. +// +// GitHub API docs: https://docs.github.com/en/rest/users/users#get-contextual-information-for-a-user +func (s *UsersService) GetHovercard(ctx context.Context, user string, opts *HovercardOptions) (*Hovercard, *Response, error) { + u := fmt.Sprintf("users/%v/hovercard", user) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + hc := new(Hovercard) + resp, err := s.client.Do(ctx, req, hc) + if err != nil { + return nil, resp, err + } + + return hc, resp, nil +} + +// UserListOptions specifies optional parameters to the UsersService.ListAll +// method. +type UserListOptions struct { + // ID of the last user seen + Since int64 `url:"since,omitempty"` + + // Note: Pagination is powered exclusively by the Since parameter, + // ListOptions.Page has no effect. + // ListOptions.PerPage controls an undocumented GitHub API parameter. + ListOptions +} + +// ListAll lists all GitHub users. +// +// To paginate through all users, populate 'Since' with the ID of the last user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/users#list-users +func (s *UsersService) ListAll(ctx context.Context, opts *UserListOptions) ([]*User, *Response, error) { + u, err := addOptions("users", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ListInvitations lists all currently-open repository invitations for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/invitations#list-repository-invitations-for-the-authenticated-user +func (s *UsersService) ListInvitations(ctx context.Context, opts *ListOptions) ([]*RepositoryInvitation, *Response, error) { + u, err := addOptions("user/repository_invitations", opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + invites := []*RepositoryInvitation{} + resp, err := s.client.Do(ctx, req, &invites) + if err != nil { + return nil, resp, err + } + + return invites, resp, nil +} + +// AcceptInvitation accepts the currently-open repository invitation for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/invitations#accept-a-repository-invitation +func (s *UsersService) AcceptInvitation(ctx context.Context, invitationID int64) (*Response, error) { + u := fmt.Sprintf("user/repository_invitations/%v", invitationID) + req, err := s.client.NewRequest("PATCH", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DeclineInvitation declines the currently-open repository invitation for the +// authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/collaborators/invitations#decline-a-repository-invitation +func (s *UsersService) DeclineInvitation(ctx context.Context, invitationID int64) (*Response, error) { + u := fmt.Sprintf("user/repository_invitations/%v", invitationID) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/users_administration.go b/vendor/github.com/google/go-github/v45/github/users_administration.go new file mode 100644 index 0000000000..aef947ec45 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users_administration.go @@ -0,0 +1,72 @@ +// Copyright 2014 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// PromoteSiteAdmin promotes a user to a site administrator of a GitHub Enterprise instance. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#promote-an-ordinary-user-to-a-site-administrator +func (s *UsersService) PromoteSiteAdmin(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/site_admin", user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// DemoteSiteAdmin demotes a user from site administrator of a GitHub Enterprise instance. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#demote-a-site-administrator-to-an-ordinary-user +func (s *UsersService) DemoteSiteAdmin(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/site_admin", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// UserSuspendOptions represents the reason a user is being suspended. +type UserSuspendOptions struct { + Reason *string `json:"reason,omitempty"` +} + +// Suspend a user on a GitHub Enterprise instance. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#suspend-a-user +func (s *UsersService) Suspend(ctx context.Context, user string, opts *UserSuspendOptions) (*Response, error) { + u := fmt.Sprintf("users/%v/suspended", user) + + req, err := s.client.NewRequest("PUT", u, opts) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unsuspend a user on a GitHub Enterprise instance. +// +// GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#unsuspend-a-user +func (s *UsersService) Unsuspend(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("users/%v/suspended", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/users_blocking.go b/vendor/github.com/google/go-github/v45/github/users_blocking.go new file mode 100644 index 0000000000..3d38d94789 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users_blocking.go @@ -0,0 +1,91 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListBlockedUsers lists all the blocked users by the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/blocking#list-users-blocked-by-the-authenticated-user +func (s *UsersService) ListBlockedUsers(ctx context.Context, opts *ListOptions) ([]*User, *Response, error) { + u := "user/blocks" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + var blockedUsers []*User + resp, err := s.client.Do(ctx, req, &blockedUsers) + if err != nil { + return nil, resp, err + } + + return blockedUsers, resp, nil +} + +// IsBlocked reports whether specified user is blocked by the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/blocking#check-if-a-user-is-blocked-by-the-authenticated-user +func (s *UsersService) IsBlocked(ctx context.Context, user string) (bool, *Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + resp, err := s.client.Do(ctx, req, nil) + isBlocked, err := parseBoolResponse(err) + return isBlocked, resp, err +} + +// BlockUser blocks specified user for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/blocking#block-a-user +func (s *UsersService) BlockUser(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} + +// UnblockUser unblocks specified user for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/blocking#unblock-a-user +func (s *UsersService) UnblockUser(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/blocks/%v", user) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeBlockUsersPreview) + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/users_emails.go b/vendor/github.com/google/go-github/v45/github/users_emails.go new file mode 100644 index 0000000000..be7e0f819e --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users_emails.go @@ -0,0 +1,72 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import "context" + +// UserEmail represents user's email address +type UserEmail struct { + Email *string `json:"email,omitempty"` + Primary *bool `json:"primary,omitempty"` + Verified *bool `json:"verified,omitempty"` + Visibility *string `json:"visibility,omitempty"` +} + +// ListEmails lists all email addresses for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user +func (s *UsersService) ListEmails(ctx context.Context, opts *ListOptions) ([]*UserEmail, *Response, error) { + u := "user/emails" + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var emails []*UserEmail + resp, err := s.client.Do(ctx, req, &emails) + if err != nil { + return nil, resp, err + } + + return emails, resp, nil +} + +// AddEmails adds email addresses of the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/emails#add-an-email-address-for-the-authenticated-user +func (s *UsersService) AddEmails(ctx context.Context, emails []string) ([]*UserEmail, *Response, error) { + u := "user/emails" + req, err := s.client.NewRequest("POST", u, emails) + if err != nil { + return nil, nil, err + } + + var e []*UserEmail + resp, err := s.client.Do(ctx, req, &e) + if err != nil { + return nil, resp, err + } + + return e, resp, nil +} + +// DeleteEmails deletes email addresses from authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/emails#delete-an-email-address-for-the-authenticated-user +func (s *UsersService) DeleteEmails(ctx context.Context, emails []string) (*Response, error) { + u := "user/emails" + req, err := s.client.NewRequest("DELETE", u, emails) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/users_followers.go b/vendor/github.com/google/go-github/v45/github/users_followers.go new file mode 100644 index 0000000000..1266e0e9ee --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users_followers.go @@ -0,0 +1,122 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListFollowers lists the followers for a user. Passing the empty string will +// fetch followers for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/followers#list-followers-of-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/users/followers#list-followers-of-a-user +func (s *UsersService) ListFollowers(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/followers", user) + } else { + u = "user/followers" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// ListFollowing lists the people that a user is following. Passing the empty +// string will list people the authenticated user is following. +// +// GitHub API docs: https://docs.github.com/en/rest/users/followers#list-the-people-the-authenticated-user-follows +// GitHub API docs: https://docs.github.com/en/rest/users/followers#list-the-people-a-user-follows +func (s *UsersService) ListFollowing(ctx context.Context, user string, opts *ListOptions) ([]*User, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/following", user) + } else { + u = "user/following" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var users []*User + resp, err := s.client.Do(ctx, req, &users) + if err != nil { + return nil, resp, err + } + + return users, resp, nil +} + +// IsFollowing checks if "user" is following "target". Passing the empty +// string for "user" will check if the authenticated user is following "target". +// +// GitHub API docs: https://docs.github.com/en/rest/users/followers#check-if-a-person-is-followed-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/users/followers#check-if-a-user-follows-another-user +func (s *UsersService) IsFollowing(ctx context.Context, user, target string) (bool, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/following/%v", user, target) + } else { + u = fmt.Sprintf("user/following/%v", target) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return false, nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + following, err := parseBoolResponse(err) + return following, resp, err +} + +// Follow will cause the authenticated user to follow the specified user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/followers#follow-a-user +func (s *UsersService) Follow(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/following/%v", user) + req, err := s.client.NewRequest("PUT", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unfollow will cause the authenticated user to unfollow the specified user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/followers#unfollow-a-user +func (s *UsersService) Unfollow(ctx context.Context, user string) (*Response, error) { + u := fmt.Sprintf("user/following/%v", user) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/users_gpg_keys.go b/vendor/github.com/google/go-github/v45/github/users_gpg_keys.go new file mode 100644 index 0000000000..e9ce62221c --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users_gpg_keys.go @@ -0,0 +1,130 @@ +// Copyright 2016 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" + "time" +) + +// GPGKey represents a GitHub user's public GPG key used to verify GPG signed commits and tags. +// +// https://developer.github.com/changes/2016-04-04-git-signing-api-preview/ +type GPGKey struct { + ID *int64 `json:"id,omitempty"` + PrimaryKeyID *int64 `json:"primary_key_id,omitempty"` + KeyID *string `json:"key_id,omitempty"` + RawKey *string `json:"raw_key,omitempty"` + PublicKey *string `json:"public_key,omitempty"` + Emails []*GPGEmail `json:"emails,omitempty"` + Subkeys []*GPGKey `json:"subkeys,omitempty"` + CanSign *bool `json:"can_sign,omitempty"` + CanEncryptComms *bool `json:"can_encrypt_comms,omitempty"` + CanEncryptStorage *bool `json:"can_encrypt_storage,omitempty"` + CanCertify *bool `json:"can_certify,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + ExpiresAt *time.Time `json:"expires_at,omitempty"` +} + +// String stringifies a GPGKey. +func (k GPGKey) String() string { + return Stringify(k) +} + +// GPGEmail represents an email address associated to a GPG key. +type GPGEmail struct { + Email *string `json:"email,omitempty"` + Verified *bool `json:"verified,omitempty"` +} + +// ListGPGKeys lists the public GPG keys for a user. Passing the empty +// string will fetch keys for the authenticated user. It requires authentication +// via Basic Auth or via OAuth with at least read:gpg_key scope. +// +// GitHub API docs: https://docs.github.com/en/rest/users/gpg-keys#list-gpg-keys-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/users/gpg-keys#list-gpg-keys-for-a-user +func (s *UsersService) ListGPGKeys(ctx context.Context, user string, opts *ListOptions) ([]*GPGKey, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/gpg_keys", user) + } else { + u = "user/gpg_keys" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*GPGKey + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetGPGKey gets extended details for a single GPG key. It requires authentication +// via Basic Auth or via OAuth with at least read:gpg_key scope. +// +// GitHub API docs: https://docs.github.com/en/rest/users/gpg-keys#get-a-gpg-key-for-the-authenticated-user +func (s *UsersService) GetGPGKey(ctx context.Context, id int64) (*GPGKey, *Response, error) { + u := fmt.Sprintf("user/gpg_keys/%v", id) + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := &GPGKey{} + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateGPGKey creates a GPG key. It requires authenticatation via Basic Auth +// or OAuth with at least write:gpg_key scope. +// +// GitHub API docs: https://docs.github.com/en/rest/users/gpg-keys#create-a-gpg-key +func (s *UsersService) CreateGPGKey(ctx context.Context, armoredPublicKey string) (*GPGKey, *Response, error) { + gpgKey := &struct { + ArmoredPublicKey string `json:"armored_public_key"` + }{ArmoredPublicKey: armoredPublicKey} + req, err := s.client.NewRequest("POST", "user/gpg_keys", gpgKey) + if err != nil { + return nil, nil, err + } + + key := &GPGKey{} + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// DeleteGPGKey deletes a GPG key. It requires authentication via Basic Auth or +// via OAuth with at least admin:gpg_key scope. +// +// GitHub API docs: https://docs.github.com/en/rest/users/gpg-keys#delete-a-gpg-key-for-the-authenticated-user +func (s *UsersService) DeleteGPGKey(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("user/gpg_keys/%v", id) + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/users_keys.go b/vendor/github.com/google/go-github/v45/github/users_keys.go new file mode 100644 index 0000000000..59d26cdefa --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users_keys.go @@ -0,0 +1,111 @@ +// Copyright 2013 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// Key represents a public SSH key used to authenticate a user or deploy script. +type Key struct { + ID *int64 `json:"id,omitempty"` + Key *string `json:"key,omitempty"` + URL *string `json:"url,omitempty"` + Title *string `json:"title,omitempty"` + ReadOnly *bool `json:"read_only,omitempty"` + Verified *bool `json:"verified,omitempty"` + CreatedAt *Timestamp `json:"created_at,omitempty"` +} + +func (k Key) String() string { + return Stringify(k) +} + +// ListKeys lists the verified public keys for a user. Passing the empty +// string will fetch keys for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/keys#list-public-ssh-keys-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/users/keys#list-public-keys-for-a-user +func (s *UsersService) ListKeys(ctx context.Context, user string, opts *ListOptions) ([]*Key, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/keys", user) + } else { + u = "user/keys" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var keys []*Key + resp, err := s.client.Do(ctx, req, &keys) + if err != nil { + return nil, resp, err + } + + return keys, resp, nil +} + +// GetKey fetches a single public key. +// +// GitHub API docs: https://docs.github.com/en/rest/users/keys#get-a-public-ssh-key-for-the-authenticated-user +func (s *UsersService) GetKey(ctx context.Context, id int64) (*Key, *Response, error) { + u := fmt.Sprintf("user/keys/%v", id) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + key := new(Key) + resp, err := s.client.Do(ctx, req, key) + if err != nil { + return nil, resp, err + } + + return key, resp, nil +} + +// CreateKey adds a public key for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/users/keys#create-a-public-ssh-key-for-the-authenticated-user +func (s *UsersService) CreateKey(ctx context.Context, key *Key) (*Key, *Response, error) { + u := "user/keys" + + req, err := s.client.NewRequest("POST", u, key) + if err != nil { + return nil, nil, err + } + + k := new(Key) + resp, err := s.client.Do(ctx, req, k) + if err != nil { + return nil, resp, err + } + + return k, resp, nil +} + +// DeleteKey deletes a public key. +// +// GitHub API docs: https://docs.github.com/en/rest/users/keys#delete-a-public-ssh-key-for-the-authenticated-user +func (s *UsersService) DeleteKey(ctx context.Context, id int64) (*Response, error) { + u := fmt.Sprintf("user/keys/%v", id) + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/users_packages.go b/vendor/github.com/google/go-github/v45/github/users_packages.go new file mode 100644 index 0000000000..da04919ecc --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users_packages.go @@ -0,0 +1,211 @@ +// Copyright 2021 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// List the packages for a user. Passing the empty string for "user" will +// list packages for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#list-packages-for-the-authenticated-users-namespace +// GitHub API docs: https://docs.github.com/en/rest/packages#list-packages-for-a-user +func (s *UsersService) ListPackages(ctx context.Context, user string, opts *PackageListOptions) ([]*Package, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages", user) + } else { + u = "user/packages" + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var packages []*Package + resp, err := s.client.Do(ctx, req, &packages) + if err != nil { + return nil, resp, err + } + + return packages, resp, nil +} + +// Get a package by name for a user. Passing the empty string for "user" will +// get the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#get-a-package-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/packages#get-a-package-for-a-user +func (s *UsersService) GetPackage(ctx context.Context, user, packageType, packageName string) (*Package, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v", packageType, packageName) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var pack *Package + resp, err := s.client.Do(ctx, req, &pack) + if err != nil { + return nil, resp, err + } + + return pack, resp, nil +} + +// Delete a package from a user. Passing the empty string for "user" will +// delete the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#delete-a-package-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/packages#delete-a-package-for-a-user +func (s *UsersService) DeletePackage(ctx context.Context, user, packageType, packageName string) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v", packageType, packageName) + } + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Restore a package to a user. Passing the empty string for "user" will +// restore the package for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#restore-a-package-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/packages#restore-a-package-for-a-user +func (s *UsersService) RestorePackage(ctx context.Context, user, packageType, packageName string) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/restore", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v/restore", packageType, packageName) + } + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Get all versions of a package for a user. Passing the empty string for "user" will +// get versions for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#get-all-package-versions-for-a-package-owned-by-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/packages#get-all-package-versions-for-a-package-owned-by-a-user +func (s *UsersService) PackageGetAllVersions(ctx context.Context, user, packageType, packageName string, opts *PackageListOptions) ([]*PackageVersion, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions", user, packageType, packageName) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions", packageType, packageName) + } + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var versions []*PackageVersion + resp, err := s.client.Do(ctx, req, &versions) + if err != nil { + return nil, resp, err + } + + return versions, resp, nil +} + +// Get a specific version of a package for a user. Passing the empty string for "user" will +// get the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#get-a-package-version-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/packages#get-a-package-version-for-a-user +func (s *UsersService) PackageGetVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*PackageVersion, *Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var version *PackageVersion + resp, err := s.client.Do(ctx, req, &version) + if err != nil { + return nil, resp, err + } + + return version, resp, nil +} + +// Delete a package version for a user. Passing the empty string for "user" will +// delete the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#delete-a-package-version-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/packages#delete-package-version-for-a-user +func (s *UsersService) PackageDeleteVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("DELETE", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Restore a package version to a user. Passing the empty string for "user" will +// restore the version for the authenticated user. +// +// GitHub API docs: https://docs.github.com/en/rest/packages#restore-a-package-version-for-the-authenticated-user +// GitHub API docs: https://docs.github.com/en/rest/packages#restore-package-version-for-a-user +func (s *UsersService) PackageRestoreVersion(ctx context.Context, user, packageType, packageName string, packageVersionID int64) (*Response, error) { + var u string + if user != "" { + u = fmt.Sprintf("users/%v/packages/%v/%v/versions/%v/restore", user, packageType, packageName, packageVersionID) + } else { + u = fmt.Sprintf("user/packages/%v/%v/versions/%v/restore", packageType, packageName, packageVersionID) + } + + req, err := s.client.NewRequest("POST", u, nil) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} diff --git a/vendor/github.com/google/go-github/v45/github/users_projects.go b/vendor/github.com/google/go-github/v45/github/users_projects.go new file mode 100644 index 0000000000..0cbd61f923 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/users_projects.go @@ -0,0 +1,68 @@ +// Copyright 2019 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package github + +import ( + "context" + "fmt" +) + +// ListProjects lists the projects for the specified user. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#list-user-projects +func (s *UsersService) ListProjects(ctx context.Context, user string, opts *ProjectListOptions) ([]*Project, *Response, error) { + u := fmt.Sprintf("users/%v/projects", user) + u, err := addOptions(u, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + var projects []*Project + resp, err := s.client.Do(ctx, req, &projects) + if err != nil { + return nil, resp, err + } + + return projects, resp, nil +} + +// CreateUserProjectOptions specifies the parameters to the UsersService.CreateProject method. +type CreateUserProjectOptions struct { + // The name of the project. (Required.) + Name string `json:"name"` + // The description of the project. (Optional.) + Body *string `json:"body,omitempty"` +} + +// CreateProject creates a GitHub Project for the current user. +// +// GitHub API docs: https://docs.github.com/en/rest/projects/projects#create-a-user-project +func (s *UsersService) CreateProject(ctx context.Context, opts *CreateUserProjectOptions) (*Project, *Response, error) { + u := "user/projects" + req, err := s.client.NewRequest("POST", u, opts) + if err != nil { + return nil, nil, err + } + + // TODO: remove custom Accept header when this API fully launches. + req.Header.Set("Accept", mediaTypeProjectsPreview) + + project := &Project{} + resp, err := s.client.Do(ctx, req, project) + if err != nil { + return nil, resp, err + } + + return project, resp, nil +} diff --git a/vendor/github.com/google/go-github/v45/github/with_appengine.go b/vendor/github.com/google/go-github/v45/github/with_appengine.go new file mode 100644 index 0000000000..9053ce1059 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/with_appengine.go @@ -0,0 +1,21 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build appengine +// +build appengine + +// This file provides glue for making github work on App Engine. + +package github + +import ( + "context" + "net/http" +) + +func withContext(ctx context.Context, req *http.Request) *http.Request { + // No-op because App Engine adds context to a request differently. + return req +} diff --git a/vendor/github.com/google/go-github/v45/github/without_appengine.go b/vendor/github.com/google/go-github/v45/github/without_appengine.go new file mode 100644 index 0000000000..0024ae4157 --- /dev/null +++ b/vendor/github.com/google/go-github/v45/github/without_appengine.go @@ -0,0 +1,20 @@ +// Copyright 2017 The go-github AUTHORS. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !appengine +// +build !appengine + +// This file provides glue for making github work without App Engine. + +package github + +import ( + "context" + "net/http" +) + +func withContext(ctx context.Context, req *http.Request) *http.Request { + return req.WithContext(ctx) +} diff --git a/vendor/github.com/google/go-querystring/LICENSE b/vendor/github.com/google/go-querystring/LICENSE new file mode 100644 index 0000000000..ae121a1e46 --- /dev/null +++ b/vendor/github.com/google/go-querystring/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Google. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/google/go-querystring/query/encode.go b/vendor/github.com/google/go-querystring/query/encode.go new file mode 100644 index 0000000000..91198f819a --- /dev/null +++ b/vendor/github.com/google/go-querystring/query/encode.go @@ -0,0 +1,357 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package query implements encoding of structs into URL query parameters. +// +// As a simple example: +// +// type Options struct { +// Query string `url:"q"` +// ShowAll bool `url:"all"` +// Page int `url:"page"` +// } +// +// opt := Options{ "foo", true, 2 } +// v, _ := query.Values(opt) +// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2" +// +// The exact mapping between Go values and url.Values is described in the +// documentation for the Values() function. +package query + +import ( + "bytes" + "fmt" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +var timeType = reflect.TypeOf(time.Time{}) + +var encoderType = reflect.TypeOf(new(Encoder)).Elem() + +// Encoder is an interface implemented by any type that wishes to encode +// itself into URL values in a non-standard way. +type Encoder interface { + EncodeValues(key string, v *url.Values) error +} + +// Values returns the url.Values encoding of v. +// +// Values expects to be passed a struct, and traverses it recursively using the +// following encoding rules. +// +// Each exported struct field is encoded as a URL parameter unless +// +// - the field's tag is "-", or +// - the field is empty and its tag specifies the "omitempty" option +// +// The empty values are false, 0, any nil pointer or interface value, any array +// slice, map, or string of length zero, and any type (such as time.Time) that +// returns true for IsZero(). +// +// The URL parameter name defaults to the struct field name but can be +// specified in the struct field's tag value. The "url" key in the struct +// field's tag value is the key name, followed by an optional comma and +// options. For example: +// +// // Field is ignored by this package. +// Field int `url:"-"` +// +// // Field appears as URL parameter "myName". +// Field int `url:"myName"` +// +// // Field appears as URL parameter "myName" and the field is omitted if +// // its value is empty +// Field int `url:"myName,omitempty"` +// +// // Field appears as URL parameter "Field" (the default), but the field +// // is skipped if empty. Note the leading comma. +// Field int `url:",omitempty"` +// +// For encoding individual field values, the following type-dependent rules +// apply: +// +// Boolean values default to encoding as the strings "true" or "false". +// Including the "int" option signals that the field should be encoded as the +// strings "1" or "0". +// +// time.Time values default to encoding as RFC3339 timestamps. Including the +// "unix" option signals that the field should be encoded as a Unix time (see +// time.Unix()). The "unixmilli" and "unixnano" options will encode the number +// of milliseconds and nanoseconds, respectively, since January 1, 1970 (see +// time.UnixNano()). Including the "layout" struct tag (separate from the +// "url" tag) will use the value of the "layout" tag as a layout passed to +// time.Format. For example: +// +// // Encode a time.Time as YYYY-MM-DD +// Field time.Time `layout:"2006-01-02"` +// +// Slice and Array values default to encoding as multiple URL values of the +// same name. Including the "comma" option signals that the field should be +// encoded as a single comma-delimited value. Including the "space" option +// similarly encodes the value as a single space-delimited string. Including +// the "semicolon" option will encode the value as a semicolon-delimited string. +// Including the "brackets" option signals that the multiple URL values should +// have "[]" appended to the value name. "numbered" will append a number to +// the end of each incidence of the value name, example: +// name0=value0&name1=value1, etc. Including the "del" struct tag (separate +// from the "url" tag) will use the value of the "del" tag as the delimiter. +// For example: +// +// // Encode a slice of bools as ints ("1" for true, "0" for false), +// // separated by exclamation points "!". +// Field []bool `url:",int" del:"!"` +// +// Anonymous struct fields are usually encoded as if their inner exported +// fields were fields in the outer struct, subject to the standard Go +// visibility rules. An anonymous struct field with a name given in its URL +// tag is treated as having that name, rather than being anonymous. +// +// Non-nil pointer values are encoded as the value pointed to. +// +// Nested structs are encoded including parent fields in value names for +// scoping. e.g: +// +// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO" +// +// All other values are encoded using their default string representation. +// +// Multiple fields that encode to the same URL parameter name will be included +// as multiple URL values of the same name. +func Values(v interface{}) (url.Values, error) { + values := make(url.Values) + val := reflect.ValueOf(v) + for val.Kind() == reflect.Ptr { + if val.IsNil() { + return values, nil + } + val = val.Elem() + } + + if v == nil { + return values, nil + } + + if val.Kind() != reflect.Struct { + return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind()) + } + + err := reflectValue(values, val, "") + return values, err +} + +// reflectValue populates the values parameter from the struct fields in val. +// Embedded structs are followed recursively (using the rules defined in the +// Values function documentation) breadth-first. +func reflectValue(values url.Values, val reflect.Value, scope string) error { + var embedded []reflect.Value + + typ := val.Type() + for i := 0; i < typ.NumField(); i++ { + sf := typ.Field(i) + if sf.PkgPath != "" && !sf.Anonymous { // unexported + continue + } + + sv := val.Field(i) + tag := sf.Tag.Get("url") + if tag == "-" { + continue + } + name, opts := parseTag(tag) + + if name == "" { + if sf.Anonymous { + v := reflect.Indirect(sv) + if v.IsValid() && v.Kind() == reflect.Struct { + // save embedded struct for later processing + embedded = append(embedded, v) + continue + } + } + + name = sf.Name + } + + if scope != "" { + name = scope + "[" + name + "]" + } + + if opts.Contains("omitempty") && isEmptyValue(sv) { + continue + } + + if sv.Type().Implements(encoderType) { + // if sv is a nil pointer and the custom encoder is defined on a non-pointer + // method receiver, set sv to the zero value of the underlying type + if !reflect.Indirect(sv).IsValid() && sv.Type().Elem().Implements(encoderType) { + sv = reflect.New(sv.Type().Elem()) + } + + m := sv.Interface().(Encoder) + if err := m.EncodeValues(name, &values); err != nil { + return err + } + continue + } + + // recursively dereference pointers. break on nil pointers + for sv.Kind() == reflect.Ptr { + if sv.IsNil() { + break + } + sv = sv.Elem() + } + + if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array { + var del string + if opts.Contains("comma") { + del = "," + } else if opts.Contains("space") { + del = " " + } else if opts.Contains("semicolon") { + del = ";" + } else if opts.Contains("brackets") { + name = name + "[]" + } else { + del = sf.Tag.Get("del") + } + + if del != "" { + s := new(bytes.Buffer) + first := true + for i := 0; i < sv.Len(); i++ { + if first { + first = false + } else { + s.WriteString(del) + } + s.WriteString(valueString(sv.Index(i), opts, sf)) + } + values.Add(name, s.String()) + } else { + for i := 0; i < sv.Len(); i++ { + k := name + if opts.Contains("numbered") { + k = fmt.Sprintf("%s%d", name, i) + } + values.Add(k, valueString(sv.Index(i), opts, sf)) + } + } + continue + } + + if sv.Type() == timeType { + values.Add(name, valueString(sv, opts, sf)) + continue + } + + if sv.Kind() == reflect.Struct { + if err := reflectValue(values, sv, name); err != nil { + return err + } + continue + } + + values.Add(name, valueString(sv, opts, sf)) + } + + for _, f := range embedded { + if err := reflectValue(values, f, scope); err != nil { + return err + } + } + + return nil +} + +// valueString returns the string representation of a value. +func valueString(v reflect.Value, opts tagOptions, sf reflect.StructField) string { + for v.Kind() == reflect.Ptr { + if v.IsNil() { + return "" + } + v = v.Elem() + } + + if v.Kind() == reflect.Bool && opts.Contains("int") { + if v.Bool() { + return "1" + } + return "0" + } + + if v.Type() == timeType { + t := v.Interface().(time.Time) + if opts.Contains("unix") { + return strconv.FormatInt(t.Unix(), 10) + } + if opts.Contains("unixmilli") { + return strconv.FormatInt((t.UnixNano() / 1e6), 10) + } + if opts.Contains("unixnano") { + return strconv.FormatInt(t.UnixNano(), 10) + } + if layout := sf.Tag.Get("layout"); layout != "" { + return t.Format(layout) + } + return t.Format(time.RFC3339) + } + + return fmt.Sprint(v.Interface()) +} + +// isEmptyValue checks if a value should be considered empty for the purposes +// of omitting fields with the "omitempty" option. +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + + type zeroable interface { + IsZero() bool + } + + if z, ok := v.Interface().(zeroable); ok { + return z.IsZero() + } + + return false +} + +// tagOptions is the string following a comma in a struct field's "url" tag, or +// the empty string. It does not include the leading comma. +type tagOptions []string + +// parseTag splits a struct field's url tag into its name and comma-separated +// options. +func parseTag(tag string) (string, tagOptions) { + s := strings.Split(tag, ",") + return s[0], s[1:] +} + +// Contains checks whether the tagOptions contains the specified option. +func (o tagOptions) Contains(option string) bool { + for _, s := range o { + if s == option { + return true + } + } + return false +} diff --git a/vendor/github.com/mark3labs/mcp-go/mcp/prompts.go b/vendor/github.com/mark3labs/mcp-go/mcp/prompts.go deleted file mode 100644 index a63a214503..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/mcp/prompts.go +++ /dev/null @@ -1,170 +0,0 @@ -package mcp - -/* Prompts */ - -// ListPromptsRequest is sent from the client to request a list of prompts and -// prompt templates the server has. -type ListPromptsRequest struct { - PaginatedRequest -} - -// ListPromptsResult is the server's response to a prompts/list request from -// the client. -type ListPromptsResult struct { - PaginatedResult - Prompts []Prompt `json:"prompts"` -} - -// GetPromptRequest is used by the client to get a prompt provided by the -// server. -type GetPromptRequest struct { - Request - Params GetPromptParams `json:"params"` -} - -type GetPromptParams struct { - // The name of the prompt or prompt template. - Name string `json:"name"` - // Arguments to use for templating the prompt. - Arguments map[string]string `json:"arguments,omitempty"` -} - -// GetPromptResult is the server's response to a prompts/get request from the -// client. -type GetPromptResult struct { - Result - // An optional description for the prompt. - Description string `json:"description,omitempty"` - Messages []PromptMessage `json:"messages"` -} - -// Prompt represents a prompt or prompt template that the server offers. -// If Arguments is non-nil and non-empty, this indicates the prompt is a template -// that requires argument values to be provided when calling prompts/get. -// If Arguments is nil or empty, this is a static prompt that takes no arguments. -type Prompt struct { - // The name of the prompt or prompt template. - Name string `json:"name"` - // An optional description of what this prompt provides - Description string `json:"description,omitempty"` - // A list of arguments to use for templating the prompt. - // The presence of arguments indicates this is a template prompt. - Arguments []PromptArgument `json:"arguments,omitempty"` -} - -// GetName returns the name of the prompt. -func (p Prompt) GetName() string { - return p.Name -} - -// PromptArgument describes an argument that a prompt template can accept. -// When a prompt includes arguments, clients must provide values for all -// required arguments when making a prompts/get request. -type PromptArgument struct { - // The name of the argument. - Name string `json:"name"` - // A human-readable description of the argument. - Description string `json:"description,omitempty"` - // Whether this argument must be provided. - // If true, clients must include this argument when calling prompts/get. - Required bool `json:"required,omitempty"` -} - -// Role represents the sender or recipient of messages and data in a -// conversation. -type Role string - -const ( - RoleUser Role = "user" - RoleAssistant Role = "assistant" -) - -// PromptMessage describes a message returned as part of a prompt. -// -// This is similar to `SamplingMessage`, but also supports the embedding of -// resources from the MCP server. -type PromptMessage struct { - Role Role `json:"role"` - Content Content `json:"content"` // Can be TextContent, ImageContent, AudioContent or EmbeddedResource -} - -// PromptListChangedNotification is an optional notification from the server -// to the client, informing it that the list of prompts it offers has changed. This -// may be issued by servers without any previous subscription from the client. -type PromptListChangedNotification struct { - Notification -} - -// PromptOption is a function that configures a Prompt. -// It provides a flexible way to set various properties of a Prompt using the functional options pattern. -type PromptOption func(*Prompt) - -// ArgumentOption is a function that configures a PromptArgument. -// It allows for flexible configuration of prompt arguments using the functional options pattern. -type ArgumentOption func(*PromptArgument) - -// -// Core Prompt Functions -// - -// NewPrompt creates a new Prompt with the given name and options. -// The prompt will be configured based on the provided options. -// Options are applied in order, allowing for flexible prompt configuration. -func NewPrompt(name string, opts ...PromptOption) Prompt { - prompt := Prompt{ - Name: name, - } - - for _, opt := range opts { - opt(&prompt) - } - - return prompt -} - -// WithPromptDescription adds a description to the Prompt. -// The description should provide a clear, human-readable explanation of what the prompt does. -func WithPromptDescription(description string) PromptOption { - return func(p *Prompt) { - p.Description = description - } -} - -// WithArgument adds an argument to the prompt's argument list. -// The argument will be configured based on the provided options. -func WithArgument(name string, opts ...ArgumentOption) PromptOption { - return func(p *Prompt) { - arg := PromptArgument{ - Name: name, - } - - for _, opt := range opts { - opt(&arg) - } - - if p.Arguments == nil { - p.Arguments = make([]PromptArgument, 0) - } - p.Arguments = append(p.Arguments, arg) - } -} - -// -// Argument Options -// - -// ArgumentDescription adds a description to a prompt argument. -// The description should explain the purpose and expected values of the argument. -func ArgumentDescription(desc string) ArgumentOption { - return func(arg *PromptArgument) { - arg.Description = desc - } -} - -// RequiredArgument marks an argument as required in the prompt. -// Required arguments must be provided when getting the prompt. -func RequiredArgument() ArgumentOption { - return func(arg *PromptArgument) { - arg.Required = true - } -} diff --git a/vendor/github.com/mark3labs/mcp-go/mcp/resources.go b/vendor/github.com/mark3labs/mcp-go/mcp/resources.go deleted file mode 100644 index 07a59a3223..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/mcp/resources.go +++ /dev/null @@ -1,99 +0,0 @@ -package mcp - -import "github.com/yosida95/uritemplate/v3" - -// ResourceOption is a function that configures a Resource. -// It provides a flexible way to set various properties of a Resource using the functional options pattern. -type ResourceOption func(*Resource) - -// NewResource creates a new Resource with the given URI, name and options. -// The resource will be configured based on the provided options. -// Options are applied in order, allowing for flexible resource configuration. -func NewResource(uri string, name string, opts ...ResourceOption) Resource { - resource := Resource{ - URI: uri, - Name: name, - } - - for _, opt := range opts { - opt(&resource) - } - - return resource -} - -// WithResourceDescription adds a description to the Resource. -// The description should provide a clear, human-readable explanation of what the resource represents. -func WithResourceDescription(description string) ResourceOption { - return func(r *Resource) { - r.Description = description - } -} - -// WithMIMEType sets the MIME type for the Resource. -// This should indicate the format of the resource's contents. -func WithMIMEType(mimeType string) ResourceOption { - return func(r *Resource) { - r.MIMEType = mimeType - } -} - -// WithAnnotations adds annotations to the Resource. -// Annotations can provide additional metadata about the resource's intended use. -func WithAnnotations(audience []Role, priority float64) ResourceOption { - return func(r *Resource) { - if r.Annotations == nil { - r.Annotations = &Annotations{} - } - r.Annotations.Audience = audience - r.Annotations.Priority = priority - } -} - -// ResourceTemplateOption is a function that configures a ResourceTemplate. -// It provides a flexible way to set various properties of a ResourceTemplate using the functional options pattern. -type ResourceTemplateOption func(*ResourceTemplate) - -// NewResourceTemplate creates a new ResourceTemplate with the given URI template, name and options. -// The template will be configured based on the provided options. -// Options are applied in order, allowing for flexible template configuration. -func NewResourceTemplate(uriTemplate string, name string, opts ...ResourceTemplateOption) ResourceTemplate { - template := ResourceTemplate{ - URITemplate: &URITemplate{Template: uritemplate.MustNew(uriTemplate)}, - Name: name, - } - - for _, opt := range opts { - opt(&template) - } - - return template -} - -// WithTemplateDescription adds a description to the ResourceTemplate. -// The description should provide a clear, human-readable explanation of what resources this template represents. -func WithTemplateDescription(description string) ResourceTemplateOption { - return func(t *ResourceTemplate) { - t.Description = description - } -} - -// WithTemplateMIMEType sets the MIME type for the ResourceTemplate. -// This should only be set if all resources matching this template will have the same type. -func WithTemplateMIMEType(mimeType string) ResourceTemplateOption { - return func(t *ResourceTemplate) { - t.MIMEType = mimeType - } -} - -// WithTemplateAnnotations adds annotations to the ResourceTemplate. -// Annotations can provide additional metadata about the template's intended use. -func WithTemplateAnnotations(audience []Role, priority float64) ResourceTemplateOption { - return func(t *ResourceTemplate) { - if t.Annotations == nil { - t.Annotations = &Annotations{} - } - t.Annotations.Audience = audience - t.Annotations.Priority = priority - } -} diff --git a/vendor/github.com/mark3labs/mcp-go/mcp/tools.go b/vendor/github.com/mark3labs/mcp-go/mcp/tools.go deleted file mode 100644 index 3e3931b09c..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/mcp/tools.go +++ /dev/null @@ -1,1078 +0,0 @@ -package mcp - -import ( - "encoding/json" - "errors" - "fmt" - "reflect" - "strconv" -) - -var errToolSchemaConflict = errors.New("provide either InputSchema or RawInputSchema, not both") - -// ListToolsRequest is sent from the client to request a list of tools the -// server has. -type ListToolsRequest struct { - PaginatedRequest -} - -// ListToolsResult is the server's response to a tools/list request from the -// client. -type ListToolsResult struct { - PaginatedResult - Tools []Tool `json:"tools"` -} - -// CallToolResult is the server's response to a tool call. -// -// Any errors that originate from the tool SHOULD be reported inside the result -// object, with `isError` set to true, _not_ as an MCP protocol-level error -// response. Otherwise, the LLM would not be able to see that an error occurred -// and self-correct. -// -// However, any errors in _finding_ the tool, an error indicating that the -// server does not support tool calls, or any other exceptional conditions, -// should be reported as an MCP error response. -type CallToolResult struct { - Result - Content []Content `json:"content"` // Can be TextContent, ImageContent, AudioContent, or EmbeddedResource - // Whether the tool call ended in an error. - // - // If not set, this is assumed to be false (the call was successful). - IsError bool `json:"isError,omitempty"` -} - -// CallToolRequest is used by the client to invoke a tool provided by the server. -type CallToolRequest struct { - Request - Params CallToolParams `json:"params"` -} - -type CallToolParams struct { - Name string `json:"name"` - Arguments any `json:"arguments,omitempty"` - Meta *Meta `json:"_meta,omitempty"` -} - -// GetArguments returns the Arguments as map[string]any for backward compatibility -// If Arguments is not a map, it returns an empty map -func (r CallToolRequest) GetArguments() map[string]any { - if args, ok := r.Params.Arguments.(map[string]any); ok { - return args - } - return nil -} - -// GetRawArguments returns the Arguments as-is without type conversion -// This allows users to access the raw arguments in any format -func (r CallToolRequest) GetRawArguments() any { - return r.Params.Arguments -} - -// BindArguments unmarshals the Arguments into the provided struct -// This is useful for working with strongly-typed arguments -func (r CallToolRequest) BindArguments(target any) error { - if target == nil || reflect.ValueOf(target).Kind() != reflect.Ptr { - return fmt.Errorf("target must be a non-nil pointer") - } - - // Fast-path: already raw JSON - if raw, ok := r.Params.Arguments.(json.RawMessage); ok { - return json.Unmarshal(raw, target) - } - - data, err := json.Marshal(r.Params.Arguments) - if err != nil { - return fmt.Errorf("failed to marshal arguments: %w", err) - } - - return json.Unmarshal(data, target) -} - -// GetString returns a string argument by key, or the default value if not found -func (r CallToolRequest) GetString(key string, defaultValue string) string { - args := r.GetArguments() - if val, ok := args[key]; ok { - if str, ok := val.(string); ok { - return str - } - } - return defaultValue -} - -// RequireString returns a string argument by key, or an error if not found or not a string -func (r CallToolRequest) RequireString(key string) (string, error) { - args := r.GetArguments() - if val, ok := args[key]; ok { - if str, ok := val.(string); ok { - return str, nil - } - return "", fmt.Errorf("argument %q is not a string", key) - } - return "", fmt.Errorf("required argument %q not found", key) -} - -// GetInt returns an int argument by key, or the default value if not found -func (r CallToolRequest) GetInt(key string, defaultValue int) int { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case int: - return v - case float64: - return int(v) - case string: - if i, err := strconv.Atoi(v); err == nil { - return i - } - } - } - return defaultValue -} - -// RequireInt returns an int argument by key, or an error if not found or not convertible to int -func (r CallToolRequest) RequireInt(key string) (int, error) { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case int: - return v, nil - case float64: - return int(v), nil - case string: - if i, err := strconv.Atoi(v); err == nil { - return i, nil - } - return 0, fmt.Errorf("argument %q cannot be converted to int", key) - default: - return 0, fmt.Errorf("argument %q is not an int", key) - } - } - return 0, fmt.Errorf("required argument %q not found", key) -} - -// GetFloat returns a float64 argument by key, or the default value if not found -func (r CallToolRequest) GetFloat(key string, defaultValue float64) float64 { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case float64: - return v - case int: - return float64(v) - case string: - if f, err := strconv.ParseFloat(v, 64); err == nil { - return f - } - } - } - return defaultValue -} - -// RequireFloat returns a float64 argument by key, or an error if not found or not convertible to float64 -func (r CallToolRequest) RequireFloat(key string) (float64, error) { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case float64: - return v, nil - case int: - return float64(v), nil - case string: - if f, err := strconv.ParseFloat(v, 64); err == nil { - return f, nil - } - return 0, fmt.Errorf("argument %q cannot be converted to float64", key) - default: - return 0, fmt.Errorf("argument %q is not a float64", key) - } - } - return 0, fmt.Errorf("required argument %q not found", key) -} - -// GetBool returns a bool argument by key, or the default value if not found -func (r CallToolRequest) GetBool(key string, defaultValue bool) bool { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case bool: - return v - case string: - if b, err := strconv.ParseBool(v); err == nil { - return b - } - case int: - return v != 0 - case float64: - return v != 0 - } - } - return defaultValue -} - -// RequireBool returns a bool argument by key, or an error if not found or not convertible to bool -func (r CallToolRequest) RequireBool(key string) (bool, error) { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case bool: - return v, nil - case string: - if b, err := strconv.ParseBool(v); err == nil { - return b, nil - } - return false, fmt.Errorf("argument %q cannot be converted to bool", key) - case int: - return v != 0, nil - case float64: - return v != 0, nil - default: - return false, fmt.Errorf("argument %q is not a bool", key) - } - } - return false, fmt.Errorf("required argument %q not found", key) -} - -// GetStringSlice returns a string slice argument by key, or the default value if not found -func (r CallToolRequest) GetStringSlice(key string, defaultValue []string) []string { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case []string: - return v - case []any: - result := make([]string, 0, len(v)) - for _, item := range v { - if str, ok := item.(string); ok { - result = append(result, str) - } - } - return result - } - } - return defaultValue -} - -// RequireStringSlice returns a string slice argument by key, or an error if not found or not convertible to string slice -func (r CallToolRequest) RequireStringSlice(key string) ([]string, error) { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case []string: - return v, nil - case []any: - result := make([]string, 0, len(v)) - for i, item := range v { - if str, ok := item.(string); ok { - result = append(result, str) - } else { - return nil, fmt.Errorf("item %d in argument %q is not a string", i, key) - } - } - return result, nil - default: - return nil, fmt.Errorf("argument %q is not a string slice", key) - } - } - return nil, fmt.Errorf("required argument %q not found", key) -} - -// GetIntSlice returns an int slice argument by key, or the default value if not found -func (r CallToolRequest) GetIntSlice(key string, defaultValue []int) []int { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case []int: - return v - case []any: - result := make([]int, 0, len(v)) - for _, item := range v { - switch num := item.(type) { - case int: - result = append(result, num) - case float64: - result = append(result, int(num)) - case string: - if i, err := strconv.Atoi(num); err == nil { - result = append(result, i) - } - } - } - return result - } - } - return defaultValue -} - -// RequireIntSlice returns an int slice argument by key, or an error if not found or not convertible to int slice -func (r CallToolRequest) RequireIntSlice(key string) ([]int, error) { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case []int: - return v, nil - case []any: - result := make([]int, 0, len(v)) - for i, item := range v { - switch num := item.(type) { - case int: - result = append(result, num) - case float64: - result = append(result, int(num)) - case string: - if i, err := strconv.Atoi(num); err == nil { - result = append(result, i) - } else { - return nil, fmt.Errorf("item %d in argument %q cannot be converted to int", i, key) - } - default: - return nil, fmt.Errorf("item %d in argument %q is not an int", i, key) - } - } - return result, nil - default: - return nil, fmt.Errorf("argument %q is not an int slice", key) - } - } - return nil, fmt.Errorf("required argument %q not found", key) -} - -// GetFloatSlice returns a float64 slice argument by key, or the default value if not found -func (r CallToolRequest) GetFloatSlice(key string, defaultValue []float64) []float64 { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case []float64: - return v - case []any: - result := make([]float64, 0, len(v)) - for _, item := range v { - switch num := item.(type) { - case float64: - result = append(result, num) - case int: - result = append(result, float64(num)) - case string: - if f, err := strconv.ParseFloat(num, 64); err == nil { - result = append(result, f) - } - } - } - return result - } - } - return defaultValue -} - -// RequireFloatSlice returns a float64 slice argument by key, or an error if not found or not convertible to float64 slice -func (r CallToolRequest) RequireFloatSlice(key string) ([]float64, error) { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case []float64: - return v, nil - case []any: - result := make([]float64, 0, len(v)) - for i, item := range v { - switch num := item.(type) { - case float64: - result = append(result, num) - case int: - result = append(result, float64(num)) - case string: - if f, err := strconv.ParseFloat(num, 64); err == nil { - result = append(result, f) - } else { - return nil, fmt.Errorf("item %d in argument %q cannot be converted to float64", i, key) - } - default: - return nil, fmt.Errorf("item %d in argument %q is not a float64", i, key) - } - } - return result, nil - default: - return nil, fmt.Errorf("argument %q is not a float64 slice", key) - } - } - return nil, fmt.Errorf("required argument %q not found", key) -} - -// GetBoolSlice returns a bool slice argument by key, or the default value if not found -func (r CallToolRequest) GetBoolSlice(key string, defaultValue []bool) []bool { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case []bool: - return v - case []any: - result := make([]bool, 0, len(v)) - for _, item := range v { - switch b := item.(type) { - case bool: - result = append(result, b) - case string: - if parsed, err := strconv.ParseBool(b); err == nil { - result = append(result, parsed) - } - case int: - result = append(result, b != 0) - case float64: - result = append(result, b != 0) - } - } - return result - } - } - return defaultValue -} - -// RequireBoolSlice returns a bool slice argument by key, or an error if not found or not convertible to bool slice -func (r CallToolRequest) RequireBoolSlice(key string) ([]bool, error) { - args := r.GetArguments() - if val, ok := args[key]; ok { - switch v := val.(type) { - case []bool: - return v, nil - case []any: - result := make([]bool, 0, len(v)) - for i, item := range v { - switch b := item.(type) { - case bool: - result = append(result, b) - case string: - if parsed, err := strconv.ParseBool(b); err == nil { - result = append(result, parsed) - } else { - return nil, fmt.Errorf("item %d in argument %q cannot be converted to bool", i, key) - } - case int: - result = append(result, b != 0) - case float64: - result = append(result, b != 0) - default: - return nil, fmt.Errorf("item %d in argument %q is not a bool", i, key) - } - } - return result, nil - default: - return nil, fmt.Errorf("argument %q is not a bool slice", key) - } - } - return nil, fmt.Errorf("required argument %q not found", key) -} - -// ToolListChangedNotification is an optional notification from the server to -// the client, informing it that the list of tools it offers has changed. This may -// be issued by servers without any previous subscription from the client. -type ToolListChangedNotification struct { - Notification -} - -// Tool represents the definition for a tool the client can call. -type Tool struct { - // The name of the tool. - Name string `json:"name"` - // A human-readable description of the tool. - Description string `json:"description,omitempty"` - // A JSON Schema object defining the expected parameters for the tool. - InputSchema ToolInputSchema `json:"inputSchema"` - // Alternative to InputSchema - allows arbitrary JSON Schema to be provided - RawInputSchema json.RawMessage `json:"-"` // Hide this from JSON marshaling - // Optional properties describing tool behavior - Annotations ToolAnnotation `json:"annotations"` -} - -// GetName returns the name of the tool. -func (t Tool) GetName() string { - return t.Name -} - -// MarshalJSON implements the json.Marshaler interface for Tool. -// It handles marshaling either InputSchema or RawInputSchema based on which is set. -func (t Tool) MarshalJSON() ([]byte, error) { - // Create a map to build the JSON structure - m := make(map[string]any, 3) - - // Add the name and description - m["name"] = t.Name - if t.Description != "" { - m["description"] = t.Description - } - - // Determine which schema to use - if t.RawInputSchema != nil { - if t.InputSchema.Type != "" { - return nil, fmt.Errorf("tool %s has both InputSchema and RawInputSchema set: %w", t.Name, errToolSchemaConflict) - } - m["inputSchema"] = t.RawInputSchema - } else { - // Use the structured InputSchema - m["inputSchema"] = t.InputSchema - } - - m["annotations"] = t.Annotations - - return json.Marshal(m) -} - -type ToolInputSchema struct { - Type string `json:"type"` - Properties map[string]any `json:"properties,omitempty"` - Required []string `json:"required,omitempty"` -} - -// MarshalJSON implements the json.Marshaler interface for ToolInputSchema. -func (tis ToolInputSchema) MarshalJSON() ([]byte, error) { - m := make(map[string]any) - m["type"] = tis.Type - - // Marshal Properties to '{}' rather than `nil` when its length equals zero - if tis.Properties != nil { - m["properties"] = tis.Properties - } - - if len(tis.Required) > 0 { - m["required"] = tis.Required - } - - return json.Marshal(m) -} - -type ToolAnnotation struct { - // Human-readable title for the tool - Title string `json:"title,omitempty"` - // If true, the tool does not modify its environment - ReadOnlyHint *bool `json:"readOnlyHint,omitempty"` - // If true, the tool may perform destructive updates - DestructiveHint *bool `json:"destructiveHint,omitempty"` - // If true, repeated calls with same args have no additional effect - IdempotentHint *bool `json:"idempotentHint,omitempty"` - // If true, tool interacts with external entities - OpenWorldHint *bool `json:"openWorldHint,omitempty"` -} - -// ToolOption is a function that configures a Tool. -// It provides a flexible way to set various properties of a Tool using the functional options pattern. -type ToolOption func(*Tool) - -// PropertyOption is a function that configures a property in a Tool's input schema. -// It allows for flexible configuration of JSON Schema properties using the functional options pattern. -type PropertyOption func(map[string]any) - -// -// Core Tool Functions -// - -// NewTool creates a new Tool with the given name and options. -// The tool will have an object-type input schema with configurable properties. -// Options are applied in order, allowing for flexible tool configuration. -func NewTool(name string, opts ...ToolOption) Tool { - tool := Tool{ - Name: name, - InputSchema: ToolInputSchema{ - Type: "object", - Properties: make(map[string]any), - Required: nil, // Will be omitted from JSON if empty - }, - Annotations: ToolAnnotation{ - Title: "", - ReadOnlyHint: ToBoolPtr(false), - DestructiveHint: ToBoolPtr(true), - IdempotentHint: ToBoolPtr(false), - OpenWorldHint: ToBoolPtr(true), - }, - } - - for _, opt := range opts { - opt(&tool) - } - - return tool -} - -// NewToolWithRawSchema creates a new Tool with the given name and a raw JSON -// Schema. This allows for arbitrary JSON Schema to be used for the tool's input -// schema. -// -// NOTE a [Tool] built in such a way is incompatible with the [ToolOption] and -// runtime errors will result from supplying a [ToolOption] to a [Tool] built -// with this function. -func NewToolWithRawSchema(name, description string, schema json.RawMessage) Tool { - tool := Tool{ - Name: name, - Description: description, - RawInputSchema: schema, - } - - return tool -} - -// WithDescription adds a description to the Tool. -// The description should provide a clear, human-readable explanation of what the tool does. -func WithDescription(description string) ToolOption { - return func(t *Tool) { - t.Description = description - } -} - -// WithToolAnnotation adds optional hints about the Tool. -func WithToolAnnotation(annotation ToolAnnotation) ToolOption { - return func(t *Tool) { - t.Annotations = annotation - } -} - -// WithTitleAnnotation sets the Title field of the Tool's Annotations. -// It provides a human-readable title for the tool. -func WithTitleAnnotation(title string) ToolOption { - return func(t *Tool) { - t.Annotations.Title = title - } -} - -// WithReadOnlyHintAnnotation sets the ReadOnlyHint field of the Tool's Annotations. -// If true, it indicates the tool does not modify its environment. -func WithReadOnlyHintAnnotation(value bool) ToolOption { - return func(t *Tool) { - t.Annotations.ReadOnlyHint = &value - } -} - -// WithDestructiveHintAnnotation sets the DestructiveHint field of the Tool's Annotations. -// If true, it indicates the tool may perform destructive updates. -func WithDestructiveHintAnnotation(value bool) ToolOption { - return func(t *Tool) { - t.Annotations.DestructiveHint = &value - } -} - -// WithIdempotentHintAnnotation sets the IdempotentHint field of the Tool's Annotations. -// If true, it indicates repeated calls with the same arguments have no additional effect. -func WithIdempotentHintAnnotation(value bool) ToolOption { - return func(t *Tool) { - t.Annotations.IdempotentHint = &value - } -} - -// WithOpenWorldHintAnnotation sets the OpenWorldHint field of the Tool's Annotations. -// If true, it indicates the tool interacts with external entities. -func WithOpenWorldHintAnnotation(value bool) ToolOption { - return func(t *Tool) { - t.Annotations.OpenWorldHint = &value - } -} - -// -// Common Property Options -// - -// Description adds a description to a property in the JSON Schema. -// The description should explain the purpose and expected values of the property. -func Description(desc string) PropertyOption { - return func(schema map[string]any) { - schema["description"] = desc - } -} - -// Required marks a property as required in the tool's input schema. -// Required properties must be provided when using the tool. -func Required() PropertyOption { - return func(schema map[string]any) { - schema["required"] = true - } -} - -// Title adds a display-friendly title to a property in the JSON Schema. -// This title can be used by UI components to show a more readable property name. -func Title(title string) PropertyOption { - return func(schema map[string]any) { - schema["title"] = title - } -} - -// -// String Property Options -// - -// DefaultString sets the default value for a string property. -// This value will be used if the property is not explicitly provided. -func DefaultString(value string) PropertyOption { - return func(schema map[string]any) { - schema["default"] = value - } -} - -// Enum specifies a list of allowed values for a string property. -// The property value must be one of the specified enum values. -func Enum(values ...string) PropertyOption { - return func(schema map[string]any) { - schema["enum"] = values - } -} - -// MaxLength sets the maximum length for a string property. -// The string value must not exceed this length. -func MaxLength(max int) PropertyOption { - return func(schema map[string]any) { - schema["maxLength"] = max - } -} - -// MinLength sets the minimum length for a string property. -// The string value must be at least this length. -func MinLength(min int) PropertyOption { - return func(schema map[string]any) { - schema["minLength"] = min - } -} - -// Pattern sets a regex pattern that a string property must match. -// The string value must conform to the specified regular expression. -func Pattern(pattern string) PropertyOption { - return func(schema map[string]any) { - schema["pattern"] = pattern - } -} - -// -// Number Property Options -// - -// DefaultNumber sets the default value for a number property. -// This value will be used if the property is not explicitly provided. -func DefaultNumber(value float64) PropertyOption { - return func(schema map[string]any) { - schema["default"] = value - } -} - -// Max sets the maximum value for a number property. -// The number value must not exceed this maximum. -func Max(max float64) PropertyOption { - return func(schema map[string]any) { - schema["maximum"] = max - } -} - -// Min sets the minimum value for a number property. -// The number value must not be less than this minimum. -func Min(min float64) PropertyOption { - return func(schema map[string]any) { - schema["minimum"] = min - } -} - -// MultipleOf specifies that a number must be a multiple of the given value. -// The number value must be divisible by this value. -func MultipleOf(value float64) PropertyOption { - return func(schema map[string]any) { - schema["multipleOf"] = value - } -} - -// -// Boolean Property Options -// - -// DefaultBool sets the default value for a boolean property. -// This value will be used if the property is not explicitly provided. -func DefaultBool(value bool) PropertyOption { - return func(schema map[string]any) { - schema["default"] = value - } -} - -// -// Array Property Options -// - -// DefaultArray sets the default value for an array property. -// This value will be used if the property is not explicitly provided. -func DefaultArray[T any](value []T) PropertyOption { - return func(schema map[string]any) { - schema["default"] = value - } -} - -// -// Property Type Helpers -// - -// WithBoolean adds a boolean property to the tool schema. -// It accepts property options to configure the boolean property's behavior and constraints. -func WithBoolean(name string, opts ...PropertyOption) ToolOption { - return func(t *Tool) { - schema := map[string]any{ - "type": "boolean", - } - - for _, opt := range opts { - opt(schema) - } - - // Remove required from property schema and add to InputSchema.required - if required, ok := schema["required"].(bool); ok && required { - delete(schema, "required") - t.InputSchema.Required = append(t.InputSchema.Required, name) - } - - t.InputSchema.Properties[name] = schema - } -} - -// WithNumber adds a number property to the tool schema. -// It accepts property options to configure the number property's behavior and constraints. -func WithNumber(name string, opts ...PropertyOption) ToolOption { - return func(t *Tool) { - schema := map[string]any{ - "type": "number", - } - - for _, opt := range opts { - opt(schema) - } - - // Remove required from property schema and add to InputSchema.required - if required, ok := schema["required"].(bool); ok && required { - delete(schema, "required") - t.InputSchema.Required = append(t.InputSchema.Required, name) - } - - t.InputSchema.Properties[name] = schema - } -} - -// WithString adds a string property to the tool schema. -// It accepts property options to configure the string property's behavior and constraints. -func WithString(name string, opts ...PropertyOption) ToolOption { - return func(t *Tool) { - schema := map[string]any{ - "type": "string", - } - - for _, opt := range opts { - opt(schema) - } - - // Remove required from property schema and add to InputSchema.required - if required, ok := schema["required"].(bool); ok && required { - delete(schema, "required") - t.InputSchema.Required = append(t.InputSchema.Required, name) - } - - t.InputSchema.Properties[name] = schema - } -} - -// WithObject adds an object property to the tool schema. -// It accepts property options to configure the object property's behavior and constraints. -func WithObject(name string, opts ...PropertyOption) ToolOption { - return func(t *Tool) { - schema := map[string]any{ - "type": "object", - "properties": map[string]any{}, - } - - for _, opt := range opts { - opt(schema) - } - - // Remove required from property schema and add to InputSchema.required - if required, ok := schema["required"].(bool); ok && required { - delete(schema, "required") - t.InputSchema.Required = append(t.InputSchema.Required, name) - } - - t.InputSchema.Properties[name] = schema - } -} - -// WithArray adds an array property to the tool schema. -// It accepts property options to configure the array property's behavior and constraints. -func WithArray(name string, opts ...PropertyOption) ToolOption { - return func(t *Tool) { - schema := map[string]any{ - "type": "array", - } - - for _, opt := range opts { - opt(schema) - } - - // Remove required from property schema and add to InputSchema.required - if required, ok := schema["required"].(bool); ok && required { - delete(schema, "required") - t.InputSchema.Required = append(t.InputSchema.Required, name) - } - - t.InputSchema.Properties[name] = schema - } -} - -// Properties defines the properties for an object schema -func Properties(props map[string]any) PropertyOption { - return func(schema map[string]any) { - schema["properties"] = props - } -} - -// AdditionalProperties specifies whether additional properties are allowed in the object -// or defines a schema for additional properties -func AdditionalProperties(schema any) PropertyOption { - return func(schemaMap map[string]any) { - schemaMap["additionalProperties"] = schema - } -} - -// MinProperties sets the minimum number of properties for an object -func MinProperties(min int) PropertyOption { - return func(schema map[string]any) { - schema["minProperties"] = min - } -} - -// MaxProperties sets the maximum number of properties for an object -func MaxProperties(max int) PropertyOption { - return func(schema map[string]any) { - schema["maxProperties"] = max - } -} - -// PropertyNames defines a schema for property names in an object -func PropertyNames(schema map[string]any) PropertyOption { - return func(schemaMap map[string]any) { - schemaMap["propertyNames"] = schema - } -} - -// Items defines the schema for array items. -// Accepts any schema definition for maximum flexibility. -// -// Example: -// -// Items(map[string]any{ -// "type": "object", -// "properties": map[string]any{ -// "name": map[string]any{"type": "string"}, -// "age": map[string]any{"type": "number"}, -// }, -// }) -// -// For simple types, use ItemsString(), ItemsNumber(), ItemsBoolean() instead. -func Items(schema any) PropertyOption { - return func(schemaMap map[string]any) { - schemaMap["items"] = schema - } -} - -// MinItems sets the minimum number of items for an array -func MinItems(min int) PropertyOption { - return func(schema map[string]any) { - schema["minItems"] = min - } -} - -// MaxItems sets the maximum number of items for an array -func MaxItems(max int) PropertyOption { - return func(schema map[string]any) { - schema["maxItems"] = max - } -} - -// UniqueItems specifies whether array items must be unique -func UniqueItems(unique bool) PropertyOption { - return func(schema map[string]any) { - schema["uniqueItems"] = unique - } -} - -// WithStringItems configures an array's items to be of type string. -// -// Supported options: Description(), DefaultString(), Enum(), MaxLength(), MinLength(), Pattern() -// Note: Options like Required() are not valid for item schemas and will be ignored. -// -// Examples: -// -// mcp.WithArray("tags", mcp.WithStringItems()) -// mcp.WithArray("colors", mcp.WithStringItems(mcp.Enum("red", "green", "blue"))) -// mcp.WithArray("names", mcp.WithStringItems(mcp.MinLength(1), mcp.MaxLength(50))) -// -// Limitations: Only supports simple string arrays. Use Items() for complex objects. -func WithStringItems(opts ...PropertyOption) PropertyOption { - return func(schema map[string]any) { - itemSchema := map[string]any{ - "type": "string", - } - - for _, opt := range opts { - opt(itemSchema) - } - - schema["items"] = itemSchema - } -} - -// WithStringEnumItems configures an array's items to be of type string with a specified enum. -// Example: -// -// mcp.WithArray("priority", mcp.WithStringEnumItems([]string{"low", "medium", "high"})) -// -// Limitations: Only supports string enums. Use WithStringItems(Enum(...)) for more flexibility. -func WithStringEnumItems(values []string) PropertyOption { - return func(schema map[string]any) { - schema["items"] = map[string]any{ - "type": "string", - "enum": values, - } - } -} - -// WithNumberItems configures an array's items to be of type number. -// -// Supported options: Description(), DefaultNumber(), Min(), Max(), MultipleOf() -// Note: Options like Required() are not valid for item schemas and will be ignored. -// -// Examples: -// -// mcp.WithArray("scores", mcp.WithNumberItems(mcp.Min(0), mcp.Max(100))) -// mcp.WithArray("prices", mcp.WithNumberItems(mcp.Min(0))) -// -// Limitations: Only supports simple number arrays. Use Items() for complex objects. -func WithNumberItems(opts ...PropertyOption) PropertyOption { - return func(schema map[string]any) { - itemSchema := map[string]any{ - "type": "number", - } - - for _, opt := range opts { - opt(itemSchema) - } - - schema["items"] = itemSchema - } -} - -// WithBooleanItems configures an array's items to be of type boolean. -// -// Supported options: Description(), DefaultBool() -// Note: Options like Required() are not valid for item schemas and will be ignored. -// -// Examples: -// -// mcp.WithArray("flags", mcp.WithBooleanItems()) -// mcp.WithArray("permissions", mcp.WithBooleanItems(mcp.Description("User permissions"))) -// -// Limitations: Only supports simple boolean arrays. Use Items() for complex objects. -func WithBooleanItems(opts ...PropertyOption) PropertyOption { - return func(schema map[string]any) { - itemSchema := map[string]any{ - "type": "boolean", - } - - for _, opt := range opts { - opt(itemSchema) - } - - schema["items"] = itemSchema - } -} diff --git a/vendor/github.com/mark3labs/mcp-go/mcp/typed_tools.go b/vendor/github.com/mark3labs/mcp-go/mcp/typed_tools.go deleted file mode 100644 index 68d8cdd1f3..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/mcp/typed_tools.go +++ /dev/null @@ -1,20 +0,0 @@ -package mcp - -import ( - "context" - "fmt" -) - -// TypedToolHandlerFunc is a function that handles a tool call with typed arguments -type TypedToolHandlerFunc[T any] func(ctx context.Context, request CallToolRequest, args T) (*CallToolResult, error) - -// NewTypedToolHandler creates a ToolHandlerFunc that automatically binds arguments to a typed struct -func NewTypedToolHandler[T any](handler TypedToolHandlerFunc[T]) func(ctx context.Context, request CallToolRequest) (*CallToolResult, error) { - return func(ctx context.Context, request CallToolRequest) (*CallToolResult, error) { - var args T - if err := request.BindArguments(&args); err != nil { - return NewToolResultError(fmt.Sprintf("failed to bind arguments: %v", err)), nil - } - return handler(ctx, request, args) - } -} diff --git a/vendor/github.com/mark3labs/mcp-go/mcp/types.go b/vendor/github.com/mark3labs/mcp-go/mcp/types.go deleted file mode 100644 index 241b55ce9b..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/mcp/types.go +++ /dev/null @@ -1,1065 +0,0 @@ -// Package mcp defines the core types and interfaces for the Model Context Protocol (MCP). -// MCP is a protocol for communication between LLM-powered applications and their supporting services. -package mcp - -import ( - "encoding/json" - "fmt" - "maps" - "strconv" - - "github.com/yosida95/uritemplate/v3" -) - -type MCPMethod string - -const ( - // MethodInitialize initiates connection and negotiates protocol capabilities. - // https://modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle/#initialization - MethodInitialize MCPMethod = "initialize" - - // MethodPing verifies connection liveness between client and server. - // https://modelcontextprotocol.io/specification/2024-11-05/basic/utilities/ping/ - MethodPing MCPMethod = "ping" - - // MethodResourcesList lists all available server resources. - // https://modelcontextprotocol.io/specification/2024-11-05/server/resources/ - MethodResourcesList MCPMethod = "resources/list" - - // MethodResourcesTemplatesList provides URI templates for constructing resource URIs. - // https://modelcontextprotocol.io/specification/2024-11-05/server/resources/ - MethodResourcesTemplatesList MCPMethod = "resources/templates/list" - - // MethodResourcesRead retrieves content of a specific resource by URI. - // https://modelcontextprotocol.io/specification/2024-11-05/server/resources/ - MethodResourcesRead MCPMethod = "resources/read" - - // MethodPromptsList lists all available prompt templates. - // https://modelcontextprotocol.io/specification/2024-11-05/server/prompts/ - MethodPromptsList MCPMethod = "prompts/list" - - // MethodPromptsGet retrieves a specific prompt template with filled parameters. - // https://modelcontextprotocol.io/specification/2024-11-05/server/prompts/ - MethodPromptsGet MCPMethod = "prompts/get" - - // MethodToolsList lists all available executable tools. - // https://modelcontextprotocol.io/specification/2024-11-05/server/tools/ - MethodToolsList MCPMethod = "tools/list" - - // MethodToolsCall invokes a specific tool with provided parameters. - // https://modelcontextprotocol.io/specification/2024-11-05/server/tools/ - MethodToolsCall MCPMethod = "tools/call" - - // MethodSetLogLevel configures the minimum log level for client - // https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/logging - MethodSetLogLevel MCPMethod = "logging/setLevel" - - // MethodNotificationResourcesListChanged notifies when the list of available resources changes. - // https://modelcontextprotocol.io/specification/2025-03-26/server/resources#list-changed-notification - MethodNotificationResourcesListChanged = "notifications/resources/list_changed" - - MethodNotificationResourceUpdated = "notifications/resources/updated" - - // MethodNotificationPromptsListChanged notifies when the list of available prompt templates changes. - // https://modelcontextprotocol.io/specification/2025-03-26/server/prompts#list-changed-notification - MethodNotificationPromptsListChanged = "notifications/prompts/list_changed" - - // MethodNotificationToolsListChanged notifies when the list of available tools changes. - // https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/list_changed/ - MethodNotificationToolsListChanged = "notifications/tools/list_changed" -) - -type URITemplate struct { - *uritemplate.Template -} - -func (t *URITemplate) MarshalJSON() ([]byte, error) { - return json.Marshal(t.Raw()) -} - -func (t *URITemplate) UnmarshalJSON(data []byte) error { - var raw string - if err := json.Unmarshal(data, &raw); err != nil { - return err - } - template, err := uritemplate.New(raw) - if err != nil { - return err - } - t.Template = template - return nil -} - -/* JSON-RPC types */ - -// JSONRPCMessage represents either a JSONRPCRequest, JSONRPCNotification, JSONRPCResponse, or JSONRPCError -type JSONRPCMessage any - -// LATEST_PROTOCOL_VERSION is the most recent version of the MCP protocol. -const LATEST_PROTOCOL_VERSION = "2025-03-26" - -// ValidProtocolVersions lists all known valid MCP protocol versions. -var ValidProtocolVersions = []string{ - "2024-11-05", - LATEST_PROTOCOL_VERSION, -} - -// JSONRPC_VERSION is the version of JSON-RPC used by MCP. -const JSONRPC_VERSION = "2.0" - -// ProgressToken is used to associate progress notifications with the original request. -type ProgressToken any - -// Cursor is an opaque token used to represent a cursor for pagination. -type Cursor string - -// Meta is metadata attached to a request's parameters. This can include fields -// formally defined by the protocol or other arbitrary data. -type Meta struct { - // If specified, the caller is requesting out-of-band progress - // notifications for this request (as represented by - // notifications/progress). The value of this parameter is an - // opaque token that will be attached to any subsequent - // notifications. The receiver is not obligated to provide these - // notifications. - ProgressToken ProgressToken - - // AdditionalFields are any fields present in the Meta that are not - // otherwise defined in the protocol. - AdditionalFields map[string]any -} - -func (m *Meta) MarshalJSON() ([]byte, error) { - raw := make(map[string]any) - if m.ProgressToken != nil { - raw["progressToken"] = m.ProgressToken - } - maps.Copy(raw, m.AdditionalFields) - - return json.Marshal(raw) -} - -func (m *Meta) UnmarshalJSON(data []byte) error { - raw := make(map[string]any) - if err := json.Unmarshal(data, &raw); err != nil { - return err - } - m.ProgressToken = raw["progressToken"] - delete(raw, "progressToken") - m.AdditionalFields = raw - return nil -} - -type Request struct { - Method string `json:"method"` - Params RequestParams `json:"params,omitempty"` -} - -type RequestParams struct { - Meta *Meta `json:"_meta,omitempty"` -} - -type Params map[string]any - -type Notification struct { - Method string `json:"method"` - Params NotificationParams `json:"params,omitempty"` -} - -type NotificationParams struct { - // This parameter name is reserved by MCP to allow clients and - // servers to attach additional metadata to their notifications. - Meta map[string]any `json:"_meta,omitempty"` - - // Additional fields can be added to this map - AdditionalFields map[string]any `json:"-"` -} - -// MarshalJSON implements custom JSON marshaling -func (p NotificationParams) MarshalJSON() ([]byte, error) { - // Create a map to hold all fields - m := make(map[string]any) - - // Add Meta if it exists - if p.Meta != nil { - m["_meta"] = p.Meta - } - - // Add all additional fields - for k, v := range p.AdditionalFields { - // Ensure we don't override the _meta field - if k != "_meta" { - m[k] = v - } - } - - return json.Marshal(m) -} - -// UnmarshalJSON implements custom JSON unmarshaling -func (p *NotificationParams) UnmarshalJSON(data []byte) error { - // Create a map to hold all fields - var m map[string]any - if err := json.Unmarshal(data, &m); err != nil { - return err - } - - // Initialize maps if they're nil - if p.Meta == nil { - p.Meta = make(map[string]any) - } - if p.AdditionalFields == nil { - p.AdditionalFields = make(map[string]any) - } - - // Process all fields - for k, v := range m { - if k == "_meta" { - // Handle Meta field - if meta, ok := v.(map[string]any); ok { - p.Meta = meta - } - } else { - // Handle additional fields - p.AdditionalFields[k] = v - } - } - - return nil -} - -type Result struct { - // This result property is reserved by the protocol to allow clients and - // servers to attach additional metadata to their responses. - Meta map[string]any `json:"_meta,omitempty"` -} - -// RequestId is a uniquely identifying ID for a request in JSON-RPC. -// It can be any JSON-serializable value, typically a number or string. -type RequestId struct { - value any -} - -// NewRequestId creates a new RequestId with the given value -func NewRequestId(value any) RequestId { - return RequestId{value: value} -} - -// Value returns the underlying value of the RequestId -func (r RequestId) Value() any { - return r.value -} - -// String returns a string representation of the RequestId -func (r RequestId) String() string { - switch v := r.value.(type) { - case string: - return "string:" + v - case int64: - return "int64:" + strconv.FormatInt(v, 10) - case float64: - if v == float64(int64(v)) { - return "int64:" + strconv.FormatInt(int64(v), 10) - } - return "float64:" + strconv.FormatFloat(v, 'f', -1, 64) - case nil: - return "" - default: - return "unknown:" + fmt.Sprintf("%v", v) - } -} - -// IsNil returns true if the RequestId is nil -func (r RequestId) IsNil() bool { - return r.value == nil -} - -func (r RequestId) MarshalJSON() ([]byte, error) { - return json.Marshal(r.value) -} - -func (r *RequestId) UnmarshalJSON(data []byte) error { - - if string(data) == "null" { - r.value = nil - return nil - } - - // Try unmarshaling as string first - var s string - if err := json.Unmarshal(data, &s); err == nil { - r.value = s - return nil - } - - // JSON numbers are unmarshaled as float64 in Go - var f float64 - if err := json.Unmarshal(data, &f); err == nil { - if f == float64(int64(f)) { - r.value = int64(f) - } else { - r.value = f - } - return nil - } - - return fmt.Errorf("invalid request id: %s", string(data)) -} - -// JSONRPCRequest represents a request that expects a response. -type JSONRPCRequest struct { - JSONRPC string `json:"jsonrpc"` - ID RequestId `json:"id"` - Params any `json:"params,omitempty"` - Request -} - -// JSONRPCNotification represents a notification which does not expect a response. -type JSONRPCNotification struct { - JSONRPC string `json:"jsonrpc"` - Notification -} - -// JSONRPCResponse represents a successful (non-error) response to a request. -type JSONRPCResponse struct { - JSONRPC string `json:"jsonrpc"` - ID RequestId `json:"id"` - Result any `json:"result"` -} - -// JSONRPCError represents a non-successful (error) response to a request. -type JSONRPCError struct { - JSONRPC string `json:"jsonrpc"` - ID RequestId `json:"id"` - Error struct { - // The error type that occurred. - Code int `json:"code"` - // A short description of the error. The message SHOULD be limited - // to a concise single sentence. - Message string `json:"message"` - // Additional information about the error. The value of this member - // is defined by the sender (e.g. detailed error information, nested errors etc.). - Data any `json:"data,omitempty"` - } `json:"error"` -} - -// Standard JSON-RPC error codes -const ( - PARSE_ERROR = -32700 - INVALID_REQUEST = -32600 - METHOD_NOT_FOUND = -32601 - INVALID_PARAMS = -32602 - INTERNAL_ERROR = -32603 -) - -// MCP error codes -const ( - RESOURCE_NOT_FOUND = -32002 -) - -/* Empty result */ - -// EmptyResult represents a response that indicates success but carries no data. -type EmptyResult Result - -/* Cancellation */ - -// CancelledNotification can be sent by either side to indicate that it is -// cancelling a previously-issued request. -// -// The request SHOULD still be in-flight, but due to communication latency, it -// is always possible that this notification MAY arrive after the request has -// already finished. -// -// This notification indicates that the result will be unused, so any -// associated processing SHOULD cease. -// -// A client MUST NOT attempt to cancel its `initialize` request. -type CancelledNotification struct { - Notification - Params CancelledNotificationParams `json:"params"` -} - -type CancelledNotificationParams struct { - // The ID of the request to cancel. - // - // This MUST correspond to the ID of a request previously issued - // in the same direction. - RequestId RequestId `json:"requestId"` - - // An optional string describing the reason for the cancellation. This MAY - // be logged or presented to the user. - Reason string `json:"reason,omitempty"` -} - -/* Initialization */ - -// InitializeRequest is sent from the client to the server when it first -// connects, asking it to begin initialization. -type InitializeRequest struct { - Request - Params InitializeParams `json:"params"` -} - -type InitializeParams struct { - // The latest version of the Model Context Protocol that the client supports. - // The client MAY decide to support older versions as well. - ProtocolVersion string `json:"protocolVersion"` - Capabilities ClientCapabilities `json:"capabilities"` - ClientInfo Implementation `json:"clientInfo"` -} - -// InitializeResult is sent after receiving an initialize request from the -// client. -type InitializeResult struct { - Result - // The version of the Model Context Protocol that the server wants to use. - // This may not match the version that the client requested. If the client cannot - // support this version, it MUST disconnect. - ProtocolVersion string `json:"protocolVersion"` - Capabilities ServerCapabilities `json:"capabilities"` - ServerInfo Implementation `json:"serverInfo"` - // Instructions describing how to use the server and its features. - // - // This can be used by clients to improve the LLM's understanding of - // available tools, resources, etc. It can be thought of like a "hint" to the model. - // For example, this information MAY be added to the system prompt. - Instructions string `json:"instructions,omitempty"` -} - -// InitializedNotification is sent from the client to the server after -// initialization has finished. -type InitializedNotification struct { - Notification -} - -// ClientCapabilities represents capabilities a client may support. Known -// capabilities are defined here, in this schema, but this is not a closed set: any -// client can define its own, additional capabilities. -type ClientCapabilities struct { - // Experimental, non-standard capabilities that the client supports. - Experimental map[string]any `json:"experimental,omitempty"` - // Present if the client supports listing roots. - Roots *struct { - // Whether the client supports notifications for changes to the roots list. - ListChanged bool `json:"listChanged,omitempty"` - } `json:"roots,omitempty"` - // Present if the client supports sampling from an LLM. - Sampling *struct{} `json:"sampling,omitempty"` -} - -// ServerCapabilities represents capabilities that a server may support. Known -// capabilities are defined here, in this schema, but this is not a closed set: any -// server can define its own, additional capabilities. -type ServerCapabilities struct { - // Experimental, non-standard capabilities that the server supports. - Experimental map[string]any `json:"experimental,omitempty"` - // Present if the server supports sending log messages to the client. - Logging *struct{} `json:"logging,omitempty"` - // Present if the server offers any prompt templates. - Prompts *struct { - // Whether this server supports notifications for changes to the prompt list. - ListChanged bool `json:"listChanged,omitempty"` - } `json:"prompts,omitempty"` - // Present if the server offers any resources to read. - Resources *struct { - // Whether this server supports subscribing to resource updates. - Subscribe bool `json:"subscribe,omitempty"` - // Whether this server supports notifications for changes to the resource - // list. - ListChanged bool `json:"listChanged,omitempty"` - } `json:"resources,omitempty"` - // Present if the server offers any tools to call. - Tools *struct { - // Whether this server supports notifications for changes to the tool list. - ListChanged bool `json:"listChanged,omitempty"` - } `json:"tools,omitempty"` -} - -// Implementation describes the name and version of an MCP implementation. -type Implementation struct { - Name string `json:"name"` - Version string `json:"version"` -} - -/* Ping */ - -// PingRequest represents a ping, issued by either the server or the client, -// to check that the other party is still alive. The receiver must promptly respond, -// or else may be disconnected. -type PingRequest struct { - Request -} - -/* Progress notifications */ - -// ProgressNotification is an out-of-band notification used to inform the -// receiver of a progress update for a long-running request. -type ProgressNotification struct { - Notification - Params ProgressNotificationParams `json:"params"` -} - -type ProgressNotificationParams struct { - // The progress token which was given in the initial request, used to - // associate this notification with the request that is proceeding. - ProgressToken ProgressToken `json:"progressToken"` - // The progress thus far. This should increase every time progress is made, - // even if the total is unknown. - Progress float64 `json:"progress"` - // Total number of items to process (or total progress required), if known. - Total float64 `json:"total,omitempty"` - // Message related to progress. This should provide relevant human-readable - // progress information. - Message string `json:"message,omitempty"` -} - -/* Pagination */ - -type PaginatedRequest struct { - Request - Params PaginatedParams `json:"params,omitempty"` -} - -type PaginatedParams struct { - // An opaque token representing the current pagination position. - // If provided, the server should return results starting after this cursor. - Cursor Cursor `json:"cursor,omitempty"` -} - -type PaginatedResult struct { - Result - // An opaque token representing the pagination position after the last - // returned result. - // If present, there may be more results available. - NextCursor Cursor `json:"nextCursor,omitempty"` -} - -/* Resources */ - -// ListResourcesRequest is sent from the client to request a list of resources -// the server has. -type ListResourcesRequest struct { - PaginatedRequest -} - -// ListResourcesResult is the server's response to a resources/list request -// from the client. -type ListResourcesResult struct { - PaginatedResult - Resources []Resource `json:"resources"` -} - -// ListResourceTemplatesRequest is sent from the client to request a list of -// resource templates the server has. -type ListResourceTemplatesRequest struct { - PaginatedRequest -} - -// ListResourceTemplatesResult is the server's response to a -// resources/templates/list request from the client. -type ListResourceTemplatesResult struct { - PaginatedResult - ResourceTemplates []ResourceTemplate `json:"resourceTemplates"` -} - -// ReadResourceRequest is sent from the client to the server, to read a -// specific resource URI. -type ReadResourceRequest struct { - Request - Params ReadResourceParams `json:"params"` -} - -type ReadResourceParams struct { - // The URI of the resource to read. The URI can use any protocol; it is up - // to the server how to interpret it. - URI string `json:"uri"` - // Arguments to pass to the resource handler - Arguments map[string]any `json:"arguments,omitempty"` -} - -// ReadResourceResult is the server's response to a resources/read request -// from the client. -type ReadResourceResult struct { - Result - Contents []ResourceContents `json:"contents"` // Can be TextResourceContents or BlobResourceContents -} - -// ResourceListChangedNotification is an optional notification from the server -// to the client, informing it that the list of resources it can read from has -// changed. This may be issued by servers without any previous subscription from -// the client. -type ResourceListChangedNotification struct { - Notification -} - -// SubscribeRequest is sent from the client to request resources/updated -// notifications from the server whenever a particular resource changes. -type SubscribeRequest struct { - Request - Params SubscribeParams `json:"params"` -} - -type SubscribeParams struct { - // The URI of the resource to subscribe to. The URI can use any protocol; it - // is up to the server how to interpret it. - URI string `json:"uri"` -} - -// UnsubscribeRequest is sent from the client to request cancellation of -// resources/updated notifications from the server. This should follow a previous -// resources/subscribe request. -type UnsubscribeRequest struct { - Request - Params UnsubscribeParams `json:"params"` -} - -type UnsubscribeParams struct { - // The URI of the resource to unsubscribe from. - URI string `json:"uri"` -} - -// ResourceUpdatedNotification is a notification from the server to the client, -// informing it that a resource has changed and may need to be read again. This -// should only be sent if the client previously sent a resources/subscribe request. -type ResourceUpdatedNotification struct { - Notification - Params ResourceUpdatedNotificationParams `json:"params"` -} -type ResourceUpdatedNotificationParams struct { - // The URI of the resource that has been updated. This might be a sub- - // resource of the one that the client actually subscribed to. - URI string `json:"uri"` -} - -// Resource represents a known resource that the server is capable of reading. -type Resource struct { - Annotated - // The URI of this resource. - URI string `json:"uri"` - // A human-readable name for this resource. - // - // This can be used by clients to populate UI elements. - Name string `json:"name"` - // A description of what this resource represents. - // - // This can be used by clients to improve the LLM's understanding of - // available resources. It can be thought of like a "hint" to the model. - Description string `json:"description,omitempty"` - // The MIME type of this resource, if known. - MIMEType string `json:"mimeType,omitempty"` -} - -// GetName returns the name of the resource. -func (r Resource) GetName() string { - return r.Name -} - -// ResourceTemplate represents a template description for resources available -// on the server. -type ResourceTemplate struct { - Annotated - // A URI template (according to RFC 6570) that can be used to construct - // resource URIs. - URITemplate *URITemplate `json:"uriTemplate"` - // A human-readable name for the type of resource this template refers to. - // - // This can be used by clients to populate UI elements. - Name string `json:"name"` - // A description of what this template is for. - // - // This can be used by clients to improve the LLM's understanding of - // available resources. It can be thought of like a "hint" to the model. - Description string `json:"description,omitempty"` - // The MIME type for all resources that match this template. This should only - // be included if all resources matching this template have the same type. - MIMEType string `json:"mimeType,omitempty"` -} - -// GetName returns the name of the resourceTemplate. -func (rt ResourceTemplate) GetName() string { - return rt.Name -} - -// ResourceContents represents the contents of a specific resource or sub- -// resource. -type ResourceContents interface { - isResourceContents() -} - -type TextResourceContents struct { - // The URI of this resource. - URI string `json:"uri"` - // The MIME type of this resource, if known. - MIMEType string `json:"mimeType,omitempty"` - // The text of the item. This must only be set if the item can actually be - // represented as text (not binary data). - Text string `json:"text"` -} - -func (TextResourceContents) isResourceContents() {} - -type BlobResourceContents struct { - // The URI of this resource. - URI string `json:"uri"` - // The MIME type of this resource, if known. - MIMEType string `json:"mimeType,omitempty"` - // A base64-encoded string representing the binary data of the item. - Blob string `json:"blob"` -} - -func (BlobResourceContents) isResourceContents() {} - -/* Logging */ - -// SetLevelRequest is a request from the client to the server, to enable or -// adjust logging. -type SetLevelRequest struct { - Request - Params SetLevelParams `json:"params"` -} - -type SetLevelParams struct { - // The level of logging that the client wants to receive from the server. - // The server should send all logs at this level and higher (i.e., more severe) to - // the client as notifications/logging/message. - Level LoggingLevel `json:"level"` -} - -// LoggingMessageNotification is a notification of a log message passed from -// server to client. If no logging/setLevel request has been sent from the client, -// the server MAY decide which messages to send automatically. -type LoggingMessageNotification struct { - Notification - Params LoggingMessageNotificationParams `json:"params"` -} - -type LoggingMessageNotificationParams struct { - // The severity of this log message. - Level LoggingLevel `json:"level"` - // An optional name of the logger issuing this message. - Logger string `json:"logger,omitempty"` - // The data to be logged, such as a string message or an object. Any JSON - // serializable type is allowed here. - Data any `json:"data"` -} - -// LoggingLevel represents the severity of a log message. -// -// These map to syslog message severities, as specified in RFC-5424: -// https://datatracker.ietf.org/doc/html/rfc5424#section-6.2.1 -type LoggingLevel string - -const ( - LoggingLevelDebug LoggingLevel = "debug" - LoggingLevelInfo LoggingLevel = "info" - LoggingLevelNotice LoggingLevel = "notice" - LoggingLevelWarning LoggingLevel = "warning" - LoggingLevelError LoggingLevel = "error" - LoggingLevelCritical LoggingLevel = "critical" - LoggingLevelAlert LoggingLevel = "alert" - LoggingLevelEmergency LoggingLevel = "emergency" -) - -/* Sampling */ - -const ( - // MethodSamplingCreateMessage allows servers to request LLM completions from clients - MethodSamplingCreateMessage MCPMethod = "sampling/createMessage" -) - -// CreateMessageRequest is a request from the server to sample an LLM via the -// client. The client has full discretion over which model to select. The client -// should also inform the user before beginning sampling, to allow them to inspect -// the request (human in the loop) and decide whether to approve it. -type CreateMessageRequest struct { - Request - CreateMessageParams `json:"params"` -} - -type CreateMessageParams struct { - Messages []SamplingMessage `json:"messages"` - ModelPreferences *ModelPreferences `json:"modelPreferences,omitempty"` - SystemPrompt string `json:"systemPrompt,omitempty"` - IncludeContext string `json:"includeContext,omitempty"` - Temperature float64 `json:"temperature,omitempty"` - MaxTokens int `json:"maxTokens"` - StopSequences []string `json:"stopSequences,omitempty"` - Metadata any `json:"metadata,omitempty"` -} - -// CreateMessageResult is the client's response to a sampling/create_message -// request from the server. The client should inform the user before returning the -// sampled message, to allow them to inspect the response (human in the loop) and -// decide whether to allow the server to see it. -type CreateMessageResult struct { - Result - SamplingMessage - // The name of the model that generated the message. - Model string `json:"model"` - // The reason why sampling stopped, if known. - StopReason string `json:"stopReason,omitempty"` -} - -// SamplingMessage describes a message issued to or received from an LLM API. -type SamplingMessage struct { - Role Role `json:"role"` - Content any `json:"content"` // Can be TextContent, ImageContent or AudioContent -} - -type Annotations struct { - // Describes who the intended customer of this object or data is. - // - // It can include multiple entries to indicate content useful for multiple - // audiences (e.g., `["user", "assistant"]`). - Audience []Role `json:"audience,omitempty"` - - // Describes how important this data is for operating the server. - // - // A value of 1 means "most important," and indicates that the data is - // effectively required, while 0 means "least important," and indicates that - // the data is entirely optional. - Priority float64 `json:"priority,omitempty"` -} - -// Annotated is the base for objects that include optional annotations for the -// client. The client can use annotations to inform how objects are used or -// displayed -type Annotated struct { - Annotations *Annotations `json:"annotations,omitempty"` -} - -type Content interface { - isContent() -} - -// TextContent represents text provided to or from an LLM. -// It must have Type set to "text". -type TextContent struct { - Annotated - Type string `json:"type"` // Must be "text" - // The text content of the message. - Text string `json:"text"` -} - -func (TextContent) isContent() {} - -// ImageContent represents an image provided to or from an LLM. -// It must have Type set to "image". -type ImageContent struct { - Annotated - Type string `json:"type"` // Must be "image" - // The base64-encoded image data. - Data string `json:"data"` - // The MIME type of the image. Different providers may support different image types. - MIMEType string `json:"mimeType"` -} - -func (ImageContent) isContent() {} - -// AudioContent represents the contents of audio, embedded into a prompt or tool call result. -// It must have Type set to "audio". -type AudioContent struct { - Annotated - Type string `json:"type"` // Must be "audio" - // The base64-encoded audio data. - Data string `json:"data"` - // The MIME type of the audio. Different providers may support different audio types. - MIMEType string `json:"mimeType"` -} - -func (AudioContent) isContent() {} - -// ResourceLink represents a link to a resource that the client can access. -type ResourceLink struct { - Annotated - Type string `json:"type"` // Must be "resource_link" - // The URI of the resource. - URI string `json:"uri"` - // The name of the resource. - Name string `json:"name"` - // The description of the resource. - Description string `json:"description"` - // The MIME type of the resource. - MIMEType string `json:"mimeType"` -} - -func (ResourceLink) isContent() {} - -// EmbeddedResource represents the contents of a resource, embedded into a prompt or tool call result. -// -// It is up to the client how best to render embedded resources for the -// benefit of the LLM and/or the user. -type EmbeddedResource struct { - Annotated - Type string `json:"type"` - Resource ResourceContents `json:"resource"` -} - -func (EmbeddedResource) isContent() {} - -// ModelPreferences represents the server's preferences for model selection, -// requested of the client during sampling. -// -// Because LLMs can vary along multiple dimensions, choosing the "best" modelis -// rarely straightforward. Different models excel in different areas—some are -// faster but less capable, others are more capable but more expensive, and so -// on. This interface allows servers to express their priorities across multiple -// dimensions to help clients make an appropriate selection for their use case. -// -// These preferences are always advisory. The client MAY ignore them. It is also -// up to the client to decide how to interpret these preferences and how to -// balance them against other considerations. -type ModelPreferences struct { - // Optional hints to use for model selection. - // - // If multiple hints are specified, the client MUST evaluate them in order - // (such that the first match is taken). - // - // The client SHOULD prioritize these hints over the numeric priorities, but - // MAY still use the priorities to select from ambiguous matches. - Hints []ModelHint `json:"hints,omitempty"` - - // How much to prioritize cost when selecting a model. A value of 0 means cost - // is not important, while a value of 1 means cost is the most important - // factor. - CostPriority float64 `json:"costPriority,omitempty"` - - // How much to prioritize sampling speed (latency) when selecting a model. A - // value of 0 means speed is not important, while a value of 1 means speed is - // the most important factor. - SpeedPriority float64 `json:"speedPriority,omitempty"` - - // How much to prioritize intelligence and capabilities when selecting a - // model. A value of 0 means intelligence is not important, while a value of 1 - // means intelligence is the most important factor. - IntelligencePriority float64 `json:"intelligencePriority,omitempty"` -} - -// ModelHint represents hints to use for model selection. -// -// Keys not declared here are currently left unspecified by the spec and are up -// to the client to interpret. -type ModelHint struct { - // A hint for a model name. - // - // The client SHOULD treat this as a substring of a model name; for example: - // - `claude-3-5-sonnet` should match `claude-3-5-sonnet-20241022` - // - `sonnet` should match `claude-3-5-sonnet-20241022`, `claude-3-sonnet-20240229`, etc. - // - `claude` should match any Claude model - // - // The client MAY also map the string to a different provider's model name or - // a different model family, as long as it fills a similar niche; for example: - // - `gemini-1.5-flash` could match `claude-3-haiku-20240307` - Name string `json:"name,omitempty"` -} - -/* Autocomplete */ - -// CompleteRequest is a request from the client to the server, to ask for completion options. -type CompleteRequest struct { - Request - Params CompleteParams `json:"params"` -} - -type CompleteParams struct { - Ref any `json:"ref"` // Can be PromptReference or ResourceReference - Argument struct { - // The name of the argument - Name string `json:"name"` - // The value of the argument to use for completion matching. - Value string `json:"value"` - } `json:"argument"` -} - -// CompleteResult is the server's response to a completion/complete request -type CompleteResult struct { - Result - Completion struct { - // An array of completion values. Must not exceed 100 items. - Values []string `json:"values"` - // The total number of completion options available. This can exceed the - // number of values actually sent in the response. - Total int `json:"total,omitempty"` - // Indicates whether there are additional completion options beyond those - // provided in the current response, even if the exact total is unknown. - HasMore bool `json:"hasMore,omitempty"` - } `json:"completion"` -} - -// ResourceReference is a reference to a resource or resource template definition. -type ResourceReference struct { - Type string `json:"type"` - // The URI or URI template of the resource. - URI string `json:"uri"` -} - -// PromptReference identifies a prompt. -type PromptReference struct { - Type string `json:"type"` - // The name of the prompt or prompt template - Name string `json:"name"` -} - -/* Roots */ - -// ListRootsRequest is sent from the server to request a list of root URIs from the client. Roots allow -// servers to ask for specific directories or files to operate on. A common example -// for roots is providing a set of repositories or directories a server should operate -// on. -// -// This request is typically used when the server needs to understand the file system -// structure or access specific locations that the client has permission to read from. -type ListRootsRequest struct { - Request -} - -// ListRootsResult is the client's response to a roots/list request from the server. -// This result contains an array of Root objects, each representing a root directory -// or file that the server can operate on. -type ListRootsResult struct { - Result - Roots []Root `json:"roots"` -} - -// Root represents a root directory or file that the server can operate on. -type Root struct { - // The URI identifying the root. This *must* start with file:// for now. - // This restriction may be relaxed in future versions of the protocol to allow - // other URI schemes. - URI string `json:"uri"` - // An optional name for the root. This can be used to provide a human-readable - // identifier for the root, which may be useful for display purposes or for - // referencing the root in other parts of the application. - Name string `json:"name,omitempty"` -} - -// RootsListChangedNotification is a notification from the client to the -// server, informing it that the list of roots has changed. -// This notification should be sent whenever the client adds, removes, or modifies any root. -// The server should then request an updated list of roots using the ListRootsRequest. -type RootsListChangedNotification struct { - Notification -} - -// ClientRequest represents any request that can be sent from client to server. -type ClientRequest any - -// ClientNotification represents any notification that can be sent from client to server. -type ClientNotification any - -// ClientResult represents any result that can be sent from client to server. -type ClientResult any - -// ServerRequest represents any request that can be sent from server to client. -type ServerRequest any - -// ServerNotification represents any notification that can be sent from server to client. -type ServerNotification any - -// ServerResult represents any result that can be sent from server to client. -type ServerResult any - -type Named interface { - GetName() string -} diff --git a/vendor/github.com/mark3labs/mcp-go/mcp/utils.go b/vendor/github.com/mark3labs/mcp-go/mcp/utils.go deleted file mode 100644 index 3e652efd7e..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/mcp/utils.go +++ /dev/null @@ -1,819 +0,0 @@ -package mcp - -import ( - "encoding/json" - "fmt" - - "github.com/spf13/cast" -) - -// ClientRequest types -var _ ClientRequest = &PingRequest{} -var _ ClientRequest = &InitializeRequest{} -var _ ClientRequest = &CompleteRequest{} -var _ ClientRequest = &SetLevelRequest{} -var _ ClientRequest = &GetPromptRequest{} -var _ ClientRequest = &ListPromptsRequest{} -var _ ClientRequest = &ListResourcesRequest{} -var _ ClientRequest = &ReadResourceRequest{} -var _ ClientRequest = &SubscribeRequest{} -var _ ClientRequest = &UnsubscribeRequest{} -var _ ClientRequest = &CallToolRequest{} -var _ ClientRequest = &ListToolsRequest{} - -// ClientNotification types -var _ ClientNotification = &CancelledNotification{} -var _ ClientNotification = &ProgressNotification{} -var _ ClientNotification = &InitializedNotification{} -var _ ClientNotification = &RootsListChangedNotification{} - -// ClientResult types -var _ ClientResult = &EmptyResult{} -var _ ClientResult = &CreateMessageResult{} -var _ ClientResult = &ListRootsResult{} - -// ServerRequest types -var _ ServerRequest = &PingRequest{} -var _ ServerRequest = &CreateMessageRequest{} -var _ ServerRequest = &ListRootsRequest{} - -// ServerNotification types -var _ ServerNotification = &CancelledNotification{} -var _ ServerNotification = &ProgressNotification{} -var _ ServerNotification = &LoggingMessageNotification{} -var _ ServerNotification = &ResourceUpdatedNotification{} -var _ ServerNotification = &ResourceListChangedNotification{} -var _ ServerNotification = &ToolListChangedNotification{} -var _ ServerNotification = &PromptListChangedNotification{} - -// ServerResult types -var _ ServerResult = &EmptyResult{} -var _ ServerResult = &InitializeResult{} -var _ ServerResult = &CompleteResult{} -var _ ServerResult = &GetPromptResult{} -var _ ServerResult = &ListPromptsResult{} -var _ ServerResult = &ListResourcesResult{} -var _ ServerResult = &ReadResourceResult{} -var _ ServerResult = &CallToolResult{} -var _ ServerResult = &ListToolsResult{} - -// Helper functions for type assertions - -// asType attempts to cast the given interface to the given type -func asType[T any](content any) (*T, bool) { - tc, ok := content.(T) - if !ok { - return nil, false - } - return &tc, true -} - -// AsTextContent attempts to cast the given interface to TextContent -func AsTextContent(content any) (*TextContent, bool) { - return asType[TextContent](content) -} - -// AsImageContent attempts to cast the given interface to ImageContent -func AsImageContent(content any) (*ImageContent, bool) { - return asType[ImageContent](content) -} - -// AsAudioContent attempts to cast the given interface to AudioContent -func AsAudioContent(content any) (*AudioContent, bool) { - return asType[AudioContent](content) -} - -// AsEmbeddedResource attempts to cast the given interface to EmbeddedResource -func AsEmbeddedResource(content any) (*EmbeddedResource, bool) { - return asType[EmbeddedResource](content) -} - -// AsTextResourceContents attempts to cast the given interface to TextResourceContents -func AsTextResourceContents(content any) (*TextResourceContents, bool) { - return asType[TextResourceContents](content) -} - -// AsBlobResourceContents attempts to cast the given interface to BlobResourceContents -func AsBlobResourceContents(content any) (*BlobResourceContents, bool) { - return asType[BlobResourceContents](content) -} - -// Helper function for JSON-RPC - -// NewJSONRPCResponse creates a new JSONRPCResponse with the given id and result -func NewJSONRPCResponse(id RequestId, result Result) JSONRPCResponse { - return JSONRPCResponse{ - JSONRPC: JSONRPC_VERSION, - ID: id, - Result: result, - } -} - -// NewJSONRPCError creates a new JSONRPCResponse with the given id, code, and message -func NewJSONRPCError( - id RequestId, - code int, - message string, - data any, -) JSONRPCError { - return JSONRPCError{ - JSONRPC: JSONRPC_VERSION, - ID: id, - Error: struct { - Code int `json:"code"` - Message string `json:"message"` - Data any `json:"data,omitempty"` - }{ - Code: code, - Message: message, - Data: data, - }, - } -} - -// NewProgressNotification -// Helper function for creating a progress notification -func NewProgressNotification( - token ProgressToken, - progress float64, - total *float64, - message *string, -) ProgressNotification { - notification := ProgressNotification{ - Notification: Notification{ - Method: "notifications/progress", - }, - Params: struct { - ProgressToken ProgressToken `json:"progressToken"` - Progress float64 `json:"progress"` - Total float64 `json:"total,omitempty"` - Message string `json:"message,omitempty"` - }{ - ProgressToken: token, - Progress: progress, - }, - } - if total != nil { - notification.Params.Total = *total - } - if message != nil { - notification.Params.Message = *message - } - return notification -} - -// NewLoggingMessageNotification -// Helper function for creating a logging message notification -func NewLoggingMessageNotification( - level LoggingLevel, - logger string, - data any, -) LoggingMessageNotification { - return LoggingMessageNotification{ - Notification: Notification{ - Method: "notifications/message", - }, - Params: struct { - Level LoggingLevel `json:"level"` - Logger string `json:"logger,omitempty"` - Data any `json:"data"` - }{ - Level: level, - Logger: logger, - Data: data, - }, - } -} - -// NewPromptMessage -// Helper function to create a new PromptMessage -func NewPromptMessage(role Role, content Content) PromptMessage { - return PromptMessage{ - Role: role, - Content: content, - } -} - -// NewTextContent -// Helper function to create a new TextContent -func NewTextContent(text string) TextContent { - return TextContent{ - Type: "text", - Text: text, - } -} - -// NewImageContent -// Helper function to create a new ImageContent -func NewImageContent(data, mimeType string) ImageContent { - return ImageContent{ - Type: "image", - Data: data, - MIMEType: mimeType, - } -} - -// Helper function to create a new AudioContent -func NewAudioContent(data, mimeType string) AudioContent { - return AudioContent{ - Type: "audio", - Data: data, - MIMEType: mimeType, - } -} - -// Helper function to create a new ResourceLink -func NewResourceLink(uri, name, description, mimeType string) ResourceLink { - return ResourceLink{ - Type: "resource_link", - URI: uri, - Name: name, - Description: description, - MIMEType: mimeType, - } -} - -// Helper function to create a new EmbeddedResource -func NewEmbeddedResource(resource ResourceContents) EmbeddedResource { - return EmbeddedResource{ - Type: "resource", - Resource: resource, - } -} - -// NewToolResultText creates a new CallToolResult with a text content -func NewToolResultText(text string) *CallToolResult { - return &CallToolResult{ - Content: []Content{ - TextContent{ - Type: "text", - Text: text, - }, - }, - } -} - -// NewToolResultImage creates a new CallToolResult with both text and image content -func NewToolResultImage(text, imageData, mimeType string) *CallToolResult { - return &CallToolResult{ - Content: []Content{ - TextContent{ - Type: "text", - Text: text, - }, - ImageContent{ - Type: "image", - Data: imageData, - MIMEType: mimeType, - }, - }, - } -} - -// NewToolResultAudio creates a new CallToolResult with both text and audio content -func NewToolResultAudio(text, imageData, mimeType string) *CallToolResult { - return &CallToolResult{ - Content: []Content{ - TextContent{ - Type: "text", - Text: text, - }, - AudioContent{ - Type: "audio", - Data: imageData, - MIMEType: mimeType, - }, - }, - } -} - -// NewToolResultResource creates a new CallToolResult with an embedded resource -func NewToolResultResource( - text string, - resource ResourceContents, -) *CallToolResult { - return &CallToolResult{ - Content: []Content{ - TextContent{ - Type: "text", - Text: text, - }, - EmbeddedResource{ - Type: "resource", - Resource: resource, - }, - }, - } -} - -// NewToolResultError creates a new CallToolResult with an error message. -// Any errors that originate from the tool SHOULD be reported inside the result object. -func NewToolResultError(text string) *CallToolResult { - return &CallToolResult{ - Content: []Content{ - TextContent{ - Type: "text", - Text: text, - }, - }, - IsError: true, - } -} - -// NewToolResultErrorFromErr creates a new CallToolResult with an error message. -// If an error is provided, its details will be appended to the text message. -// Any errors that originate from the tool SHOULD be reported inside the result object. -func NewToolResultErrorFromErr(text string, err error) *CallToolResult { - if err != nil { - text = fmt.Sprintf("%s: %v", text, err) - } - return &CallToolResult{ - Content: []Content{ - TextContent{ - Type: "text", - Text: text, - }, - }, - IsError: true, - } -} - -// NewToolResultErrorf creates a new CallToolResult with an error message. -// The error message is formatted using the fmt package. -// Any errors that originate from the tool SHOULD be reported inside the result object. -func NewToolResultErrorf(format string, a ...any) *CallToolResult { - return &CallToolResult{ - Content: []Content{ - TextContent{ - Type: "text", - Text: fmt.Sprintf(format, a...), - }, - }, - IsError: true, - } -} - -// NewListResourcesResult creates a new ListResourcesResult -func NewListResourcesResult( - resources []Resource, - nextCursor Cursor, -) *ListResourcesResult { - return &ListResourcesResult{ - PaginatedResult: PaginatedResult{ - NextCursor: nextCursor, - }, - Resources: resources, - } -} - -// NewListResourceTemplatesResult creates a new ListResourceTemplatesResult -func NewListResourceTemplatesResult( - templates []ResourceTemplate, - nextCursor Cursor, -) *ListResourceTemplatesResult { - return &ListResourceTemplatesResult{ - PaginatedResult: PaginatedResult{ - NextCursor: nextCursor, - }, - ResourceTemplates: templates, - } -} - -// NewReadResourceResult creates a new ReadResourceResult with text content -func NewReadResourceResult(text string) *ReadResourceResult { - return &ReadResourceResult{ - Contents: []ResourceContents{ - TextResourceContents{ - Text: text, - }, - }, - } -} - -// NewListPromptsResult creates a new ListPromptsResult -func NewListPromptsResult( - prompts []Prompt, - nextCursor Cursor, -) *ListPromptsResult { - return &ListPromptsResult{ - PaginatedResult: PaginatedResult{ - NextCursor: nextCursor, - }, - Prompts: prompts, - } -} - -// NewGetPromptResult creates a new GetPromptResult -func NewGetPromptResult( - description string, - messages []PromptMessage, -) *GetPromptResult { - return &GetPromptResult{ - Description: description, - Messages: messages, - } -} - -// NewListToolsResult creates a new ListToolsResult -func NewListToolsResult(tools []Tool, nextCursor Cursor) *ListToolsResult { - return &ListToolsResult{ - PaginatedResult: PaginatedResult{ - NextCursor: nextCursor, - }, - Tools: tools, - } -} - -// NewInitializeResult creates a new InitializeResult -func NewInitializeResult( - protocolVersion string, - capabilities ServerCapabilities, - serverInfo Implementation, - instructions string, -) *InitializeResult { - return &InitializeResult{ - ProtocolVersion: protocolVersion, - Capabilities: capabilities, - ServerInfo: serverInfo, - Instructions: instructions, - } -} - -// FormatNumberResult -// Helper for formatting numbers in tool results -func FormatNumberResult(value float64) *CallToolResult { - return NewToolResultText(fmt.Sprintf("%.2f", value)) -} - -func ExtractString(data map[string]any, key string) string { - if value, ok := data[key]; ok { - if str, ok := value.(string); ok { - return str - } - } - return "" -} - -func ExtractMap(data map[string]any, key string) map[string]any { - if value, ok := data[key]; ok { - if m, ok := value.(map[string]any); ok { - return m - } - } - return nil -} - -func ParseContent(contentMap map[string]any) (Content, error) { - contentType := ExtractString(contentMap, "type") - - switch contentType { - case "text": - text := ExtractString(contentMap, "text") - return NewTextContent(text), nil - - case "image": - data := ExtractString(contentMap, "data") - mimeType := ExtractString(contentMap, "mimeType") - if data == "" || mimeType == "" { - return nil, fmt.Errorf("image data or mimeType is missing") - } - return NewImageContent(data, mimeType), nil - - case "audio": - data := ExtractString(contentMap, "data") - mimeType := ExtractString(contentMap, "mimeType") - if data == "" || mimeType == "" { - return nil, fmt.Errorf("audio data or mimeType is missing") - } - return NewAudioContent(data, mimeType), nil - - case "resource_link": - uri := ExtractString(contentMap, "uri") - name := ExtractString(contentMap, "name") - description := ExtractString(contentMap, "description") - mimeType := ExtractString(contentMap, "mimeType") - if uri == "" || name == "" { - return nil, fmt.Errorf("resource_link uri or name is missing") - } - return NewResourceLink(uri, name, description, mimeType), nil - - case "resource": - resourceMap := ExtractMap(contentMap, "resource") - if resourceMap == nil { - return nil, fmt.Errorf("resource is missing") - } - - resourceContents, err := ParseResourceContents(resourceMap) - if err != nil { - return nil, err - } - - return NewEmbeddedResource(resourceContents), nil - } - - return nil, fmt.Errorf("unsupported content type: %s", contentType) -} - -func ParseGetPromptResult(rawMessage *json.RawMessage) (*GetPromptResult, error) { - if rawMessage == nil { - return nil, fmt.Errorf("response is nil") - } - - var jsonContent map[string]any - if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - result := GetPromptResult{} - - meta, ok := jsonContent["_meta"] - if ok { - if metaMap, ok := meta.(map[string]any); ok { - result.Meta = metaMap - } - } - - description, ok := jsonContent["description"] - if ok { - if descriptionStr, ok := description.(string); ok { - result.Description = descriptionStr - } - } - - messages, ok := jsonContent["messages"] - if ok { - messagesArr, ok := messages.([]any) - if !ok { - return nil, fmt.Errorf("messages is not an array") - } - - for _, message := range messagesArr { - messageMap, ok := message.(map[string]any) - if !ok { - return nil, fmt.Errorf("message is not an object") - } - - // Extract role - roleStr := ExtractString(messageMap, "role") - if roleStr == "" || (roleStr != string(RoleAssistant) && roleStr != string(RoleUser)) { - return nil, fmt.Errorf("unsupported role: %s", roleStr) - } - - // Extract content - contentMap, ok := messageMap["content"].(map[string]any) - if !ok { - return nil, fmt.Errorf("content is not an object") - } - - // Process content - content, err := ParseContent(contentMap) - if err != nil { - return nil, err - } - - // Append processed message - result.Messages = append(result.Messages, NewPromptMessage(Role(roleStr), content)) - - } - } - - return &result, nil -} - -func ParseCallToolResult(rawMessage *json.RawMessage) (*CallToolResult, error) { - if rawMessage == nil { - return nil, fmt.Errorf("response is nil") - } - - var jsonContent map[string]any - if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var result CallToolResult - - meta, ok := jsonContent["_meta"] - if ok { - if metaMap, ok := meta.(map[string]any); ok { - result.Meta = metaMap - } - } - - isError, ok := jsonContent["isError"] - if ok { - if isErrorBool, ok := isError.(bool); ok { - result.IsError = isErrorBool - } - } - - contents, ok := jsonContent["content"] - if !ok { - return nil, fmt.Errorf("content is missing") - } - - contentArr, ok := contents.([]any) - if !ok { - return nil, fmt.Errorf("content is not an array") - } - - for _, content := range contentArr { - // Extract content - contentMap, ok := content.(map[string]any) - if !ok { - return nil, fmt.Errorf("content is not an object") - } - - // Process content - content, err := ParseContent(contentMap) - if err != nil { - return nil, err - } - - result.Content = append(result.Content, content) - } - - return &result, nil -} - -func ParseResourceContents(contentMap map[string]any) (ResourceContents, error) { - uri := ExtractString(contentMap, "uri") - if uri == "" { - return nil, fmt.Errorf("resource uri is missing") - } - - mimeType := ExtractString(contentMap, "mimeType") - - if text := ExtractString(contentMap, "text"); text != "" { - return TextResourceContents{ - URI: uri, - MIMEType: mimeType, - Text: text, - }, nil - } - - if blob := ExtractString(contentMap, "blob"); blob != "" { - return BlobResourceContents{ - URI: uri, - MIMEType: mimeType, - Blob: blob, - }, nil - } - - return nil, fmt.Errorf("unsupported resource type") -} - -func ParseReadResourceResult(rawMessage *json.RawMessage) (*ReadResourceResult, error) { - if rawMessage == nil { - return nil, fmt.Errorf("response is nil") - } - - var jsonContent map[string]any - if err := json.Unmarshal(*rawMessage, &jsonContent); err != nil { - return nil, fmt.Errorf("failed to unmarshal response: %w", err) - } - - var result ReadResourceResult - - meta, ok := jsonContent["_meta"] - if ok { - if metaMap, ok := meta.(map[string]any); ok { - result.Meta = metaMap - } - } - - contents, ok := jsonContent["contents"] - if !ok { - return nil, fmt.Errorf("contents is missing") - } - - contentArr, ok := contents.([]any) - if !ok { - return nil, fmt.Errorf("contents is not an array") - } - - for _, content := range contentArr { - // Extract content - contentMap, ok := content.(map[string]any) - if !ok { - return nil, fmt.Errorf("content is not an object") - } - - // Process content - content, err := ParseResourceContents(contentMap) - if err != nil { - return nil, err - } - - result.Contents = append(result.Contents, content) - } - - return &result, nil -} - -func ParseArgument(request CallToolRequest, key string, defaultVal any) any { - args := request.GetArguments() - if _, ok := args[key]; !ok { - return defaultVal - } else { - return args[key] - } -} - -// ParseBoolean extracts and converts a boolean parameter from a CallToolRequest. -// If the key is not found in the Arguments map, the defaultValue is returned. -// The function uses cast.ToBool for conversion which handles various string representations -// such as "true", "yes", "1", etc. -func ParseBoolean(request CallToolRequest, key string, defaultValue bool) bool { - v := ParseArgument(request, key, defaultValue) - return cast.ToBool(v) -} - -// ParseInt64 extracts and converts an int64 parameter from a CallToolRequest. -// If the key is not found in the Arguments map, the defaultValue is returned. -func ParseInt64(request CallToolRequest, key string, defaultValue int64) int64 { - v := ParseArgument(request, key, defaultValue) - return cast.ToInt64(v) -} - -// ParseInt32 extracts and converts an int32 parameter from a CallToolRequest. -func ParseInt32(request CallToolRequest, key string, defaultValue int32) int32 { - v := ParseArgument(request, key, defaultValue) - return cast.ToInt32(v) -} - -// ParseInt16 extracts and converts an int16 parameter from a CallToolRequest. -func ParseInt16(request CallToolRequest, key string, defaultValue int16) int16 { - v := ParseArgument(request, key, defaultValue) - return cast.ToInt16(v) -} - -// ParseInt8 extracts and converts an int8 parameter from a CallToolRequest. -func ParseInt8(request CallToolRequest, key string, defaultValue int8) int8 { - v := ParseArgument(request, key, defaultValue) - return cast.ToInt8(v) -} - -// ParseInt extracts and converts an int parameter from a CallToolRequest. -func ParseInt(request CallToolRequest, key string, defaultValue int) int { - v := ParseArgument(request, key, defaultValue) - return cast.ToInt(v) -} - -// ParseUInt extracts and converts an uint parameter from a CallToolRequest. -func ParseUInt(request CallToolRequest, key string, defaultValue uint) uint { - v := ParseArgument(request, key, defaultValue) - return cast.ToUint(v) -} - -// ParseUInt64 extracts and converts an uint64 parameter from a CallToolRequest. -func ParseUInt64(request CallToolRequest, key string, defaultValue uint64) uint64 { - v := ParseArgument(request, key, defaultValue) - return cast.ToUint64(v) -} - -// ParseUInt32 extracts and converts an uint32 parameter from a CallToolRequest. -func ParseUInt32(request CallToolRequest, key string, defaultValue uint32) uint32 { - v := ParseArgument(request, key, defaultValue) - return cast.ToUint32(v) -} - -// ParseUInt16 extracts and converts an uint16 parameter from a CallToolRequest. -func ParseUInt16(request CallToolRequest, key string, defaultValue uint16) uint16 { - v := ParseArgument(request, key, defaultValue) - return cast.ToUint16(v) -} - -// ParseUInt8 extracts and converts an uint8 parameter from a CallToolRequest. -func ParseUInt8(request CallToolRequest, key string, defaultValue uint8) uint8 { - v := ParseArgument(request, key, defaultValue) - return cast.ToUint8(v) -} - -// ParseFloat32 extracts and converts a float32 parameter from a CallToolRequest. -func ParseFloat32(request CallToolRequest, key string, defaultValue float32) float32 { - v := ParseArgument(request, key, defaultValue) - return cast.ToFloat32(v) -} - -// ParseFloat64 extracts and converts a float64 parameter from a CallToolRequest. -func ParseFloat64(request CallToolRequest, key string, defaultValue float64) float64 { - v := ParseArgument(request, key, defaultValue) - return cast.ToFloat64(v) -} - -// ParseString extracts and converts a string parameter from a CallToolRequest. -func ParseString(request CallToolRequest, key string, defaultValue string) string { - v := ParseArgument(request, key, defaultValue) - return cast.ToString(v) -} - -// ParseStringMap extracts and converts a string map parameter from a CallToolRequest. -func ParseStringMap(request CallToolRequest, key string, defaultValue map[string]any) map[string]any { - v := ParseArgument(request, key, defaultValue) - return cast.ToStringMap(v) -} - -// ToBoolPtr returns a pointer to the given boolean value -func ToBoolPtr(b bool) *bool { - return &b -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/errors.go b/vendor/github.com/mark3labs/mcp-go/server/errors.go deleted file mode 100644 index ecbe91e5fb..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/errors.go +++ /dev/null @@ -1,34 +0,0 @@ -package server - -import ( - "errors" - "fmt" -) - -var ( - // Common server errors - ErrUnsupported = errors.New("not supported") - ErrResourceNotFound = errors.New("resource not found") - ErrPromptNotFound = errors.New("prompt not found") - ErrToolNotFound = errors.New("tool not found") - - // Session-related errors - ErrSessionNotFound = errors.New("session not found") - ErrSessionExists = errors.New("session already exists") - ErrSessionNotInitialized = errors.New("session not properly initialized") - ErrSessionDoesNotSupportTools = errors.New("session does not support per-session tools") - ErrSessionDoesNotSupportLogging = errors.New("session does not support setting logging level") - - // Notification-related errors - ErrNotificationNotInitialized = errors.New("notification channel not initialized") - ErrNotificationChannelBlocked = errors.New("notification channel full or blocked") -) - -// ErrDynamicPathConfig is returned when attempting to use static path methods with dynamic path configuration -type ErrDynamicPathConfig struct { - Method string -} - -func (e *ErrDynamicPathConfig) Error() string { - return fmt.Sprintf("%s cannot be used with WithDynamicBasePath. Use dynamic path logic in your router.", e.Method) -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/hooks.go b/vendor/github.com/mark3labs/mcp-go/server/hooks.go deleted file mode 100644 index 4baa1c4e05..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/hooks.go +++ /dev/null @@ -1,532 +0,0 @@ -// Code generated by `go generate`. DO NOT EDIT. -// source: server/internal/gen/hooks.go.tmpl -package server - -import ( - "context" - - "github.com/mark3labs/mcp-go/mcp" -) - -// OnRegisterSessionHookFunc is a hook that will be called when a new session is registered. -type OnRegisterSessionHookFunc func(ctx context.Context, session ClientSession) - -// OnUnregisterSessionHookFunc is a hook that will be called when a session is being unregistered. -type OnUnregisterSessionHookFunc func(ctx context.Context, session ClientSession) - -// BeforeAnyHookFunc is a function that is called after the request is -// parsed but before the method is called. -type BeforeAnyHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any) - -// OnSuccessHookFunc is a hook that will be called after the request -// successfully generates a result, but before the result is sent to the client. -type OnSuccessHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any, result any) - -// OnErrorHookFunc is a hook that will be called when an error occurs, -// either during the request parsing or the method execution. -// -// Example usage: -// ``` -// -// hooks.AddOnError(func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) { -// // Check for specific error types using errors.Is -// if errors.Is(err, ErrUnsupported) { -// // Handle capability not supported errors -// log.Printf("Capability not supported: %v", err) -// } -// -// // Use errors.As to get specific error types -// var parseErr = &UnparsableMessageError{} -// if errors.As(err, &parseErr) { -// // Access specific methods/fields of the error type -// log.Printf("Failed to parse message for method %s: %v", -// parseErr.GetMethod(), parseErr.Unwrap()) -// // Access the raw message that failed to parse -// rawMsg := parseErr.GetMessage() -// } -// -// // Check for specific resource/prompt/tool errors -// switch { -// case errors.Is(err, ErrResourceNotFound): -// log.Printf("Resource not found: %v", err) -// case errors.Is(err, ErrPromptNotFound): -// log.Printf("Prompt not found: %v", err) -// case errors.Is(err, ErrToolNotFound): -// log.Printf("Tool not found: %v", err) -// } -// }) -type OnErrorHookFunc func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) - -// OnRequestInitializationFunc is a function that called before handle diff request method -// Should any errors arise during func execution, the service will promptly return the corresponding error message. -type OnRequestInitializationFunc func(ctx context.Context, id any, message any) error - -type OnBeforeInitializeFunc func(ctx context.Context, id any, message *mcp.InitializeRequest) -type OnAfterInitializeFunc func(ctx context.Context, id any, message *mcp.InitializeRequest, result *mcp.InitializeResult) - -type OnBeforePingFunc func(ctx context.Context, id any, message *mcp.PingRequest) -type OnAfterPingFunc func(ctx context.Context, id any, message *mcp.PingRequest, result *mcp.EmptyResult) - -type OnBeforeSetLevelFunc func(ctx context.Context, id any, message *mcp.SetLevelRequest) -type OnAfterSetLevelFunc func(ctx context.Context, id any, message *mcp.SetLevelRequest, result *mcp.EmptyResult) - -type OnBeforeListResourcesFunc func(ctx context.Context, id any, message *mcp.ListResourcesRequest) -type OnAfterListResourcesFunc func(ctx context.Context, id any, message *mcp.ListResourcesRequest, result *mcp.ListResourcesResult) - -type OnBeforeListResourceTemplatesFunc func(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest) -type OnAfterListResourceTemplatesFunc func(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest, result *mcp.ListResourceTemplatesResult) - -type OnBeforeReadResourceFunc func(ctx context.Context, id any, message *mcp.ReadResourceRequest) -type OnAfterReadResourceFunc func(ctx context.Context, id any, message *mcp.ReadResourceRequest, result *mcp.ReadResourceResult) - -type OnBeforeListPromptsFunc func(ctx context.Context, id any, message *mcp.ListPromptsRequest) -type OnAfterListPromptsFunc func(ctx context.Context, id any, message *mcp.ListPromptsRequest, result *mcp.ListPromptsResult) - -type OnBeforeGetPromptFunc func(ctx context.Context, id any, message *mcp.GetPromptRequest) -type OnAfterGetPromptFunc func(ctx context.Context, id any, message *mcp.GetPromptRequest, result *mcp.GetPromptResult) - -type OnBeforeListToolsFunc func(ctx context.Context, id any, message *mcp.ListToolsRequest) -type OnAfterListToolsFunc func(ctx context.Context, id any, message *mcp.ListToolsRequest, result *mcp.ListToolsResult) - -type OnBeforeCallToolFunc func(ctx context.Context, id any, message *mcp.CallToolRequest) -type OnAfterCallToolFunc func(ctx context.Context, id any, message *mcp.CallToolRequest, result *mcp.CallToolResult) - -type Hooks struct { - OnRegisterSession []OnRegisterSessionHookFunc - OnUnregisterSession []OnUnregisterSessionHookFunc - OnBeforeAny []BeforeAnyHookFunc - OnSuccess []OnSuccessHookFunc - OnError []OnErrorHookFunc - OnRequestInitialization []OnRequestInitializationFunc - OnBeforeInitialize []OnBeforeInitializeFunc - OnAfterInitialize []OnAfterInitializeFunc - OnBeforePing []OnBeforePingFunc - OnAfterPing []OnAfterPingFunc - OnBeforeSetLevel []OnBeforeSetLevelFunc - OnAfterSetLevel []OnAfterSetLevelFunc - OnBeforeListResources []OnBeforeListResourcesFunc - OnAfterListResources []OnAfterListResourcesFunc - OnBeforeListResourceTemplates []OnBeforeListResourceTemplatesFunc - OnAfterListResourceTemplates []OnAfterListResourceTemplatesFunc - OnBeforeReadResource []OnBeforeReadResourceFunc - OnAfterReadResource []OnAfterReadResourceFunc - OnBeforeListPrompts []OnBeforeListPromptsFunc - OnAfterListPrompts []OnAfterListPromptsFunc - OnBeforeGetPrompt []OnBeforeGetPromptFunc - OnAfterGetPrompt []OnAfterGetPromptFunc - OnBeforeListTools []OnBeforeListToolsFunc - OnAfterListTools []OnAfterListToolsFunc - OnBeforeCallTool []OnBeforeCallToolFunc - OnAfterCallTool []OnAfterCallToolFunc -} - -func (c *Hooks) AddBeforeAny(hook BeforeAnyHookFunc) { - c.OnBeforeAny = append(c.OnBeforeAny, hook) -} - -func (c *Hooks) AddOnSuccess(hook OnSuccessHookFunc) { - c.OnSuccess = append(c.OnSuccess, hook) -} - -// AddOnError registers a hook function that will be called when an error occurs. -// The error parameter contains the actual error object, which can be interrogated -// using Go's error handling patterns like errors.Is and errors.As. -// -// Example: -// ``` -// // Create a channel to receive errors for testing -// errChan := make(chan error, 1) -// -// // Register hook to capture and inspect errors -// hooks := &Hooks{} -// -// hooks.AddOnError(func(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) { -// // For capability-related errors -// if errors.Is(err, ErrUnsupported) { -// // Handle capability not supported -// errChan <- err -// return -// } -// -// // For parsing errors -// var parseErr = &UnparsableMessageError{} -// if errors.As(err, &parseErr) { -// // Handle unparsable message errors -// fmt.Printf("Failed to parse %s request: %v\n", -// parseErr.GetMethod(), parseErr.Unwrap()) -// errChan <- parseErr -// return -// } -// -// // For resource/prompt/tool not found errors -// if errors.Is(err, ErrResourceNotFound) || -// errors.Is(err, ErrPromptNotFound) || -// errors.Is(err, ErrToolNotFound) { -// // Handle not found errors -// errChan <- err -// return -// } -// -// // For other errors -// errChan <- err -// }) -// -// server := NewMCPServer("test-server", "1.0.0", WithHooks(hooks)) -// ``` -func (c *Hooks) AddOnError(hook OnErrorHookFunc) { - c.OnError = append(c.OnError, hook) -} - -func (c *Hooks) beforeAny(ctx context.Context, id any, method mcp.MCPMethod, message any) { - if c == nil { - return - } - for _, hook := range c.OnBeforeAny { - hook(ctx, id, method, message) - } -} - -func (c *Hooks) onSuccess(ctx context.Context, id any, method mcp.MCPMethod, message any, result any) { - if c == nil { - return - } - for _, hook := range c.OnSuccess { - hook(ctx, id, method, message, result) - } -} - -// onError calls all registered error hooks with the error object. -// The err parameter contains the actual error that occurred, which implements -// the standard error interface and may be a wrapped error or custom error type. -// -// This allows consumer code to use Go's error handling patterns: -// - errors.Is(err, ErrUnsupported) to check for specific sentinel errors -// - errors.As(err, &customErr) to extract custom error types -// -// Common error types include: -// - ErrUnsupported: When a capability is not enabled -// - UnparsableMessageError: When request parsing fails -// - ErrResourceNotFound: When a resource is not found -// - ErrPromptNotFound: When a prompt is not found -// - ErrToolNotFound: When a tool is not found -func (c *Hooks) onError(ctx context.Context, id any, method mcp.MCPMethod, message any, err error) { - if c == nil { - return - } - for _, hook := range c.OnError { - hook(ctx, id, method, message, err) - } -} - -func (c *Hooks) AddOnRegisterSession(hook OnRegisterSessionHookFunc) { - c.OnRegisterSession = append(c.OnRegisterSession, hook) -} - -func (c *Hooks) RegisterSession(ctx context.Context, session ClientSession) { - if c == nil { - return - } - for _, hook := range c.OnRegisterSession { - hook(ctx, session) - } -} - -func (c *Hooks) AddOnUnregisterSession(hook OnUnregisterSessionHookFunc) { - c.OnUnregisterSession = append(c.OnUnregisterSession, hook) -} - -func (c *Hooks) UnregisterSession(ctx context.Context, session ClientSession) { - if c == nil { - return - } - for _, hook := range c.OnUnregisterSession { - hook(ctx, session) - } -} - -func (c *Hooks) AddOnRequestInitialization(hook OnRequestInitializationFunc) { - c.OnRequestInitialization = append(c.OnRequestInitialization, hook) -} - -func (c *Hooks) onRequestInitialization(ctx context.Context, id any, message any) error { - if c == nil { - return nil - } - for _, hook := range c.OnRequestInitialization { - err := hook(ctx, id, message) - if err != nil { - return err - } - } - return nil -} -func (c *Hooks) AddBeforeInitialize(hook OnBeforeInitializeFunc) { - c.OnBeforeInitialize = append(c.OnBeforeInitialize, hook) -} - -func (c *Hooks) AddAfterInitialize(hook OnAfterInitializeFunc) { - c.OnAfterInitialize = append(c.OnAfterInitialize, hook) -} - -func (c *Hooks) beforeInitialize(ctx context.Context, id any, message *mcp.InitializeRequest) { - c.beforeAny(ctx, id, mcp.MethodInitialize, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeInitialize { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterInitialize(ctx context.Context, id any, message *mcp.InitializeRequest, result *mcp.InitializeResult) { - c.onSuccess(ctx, id, mcp.MethodInitialize, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterInitialize { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforePing(hook OnBeforePingFunc) { - c.OnBeforePing = append(c.OnBeforePing, hook) -} - -func (c *Hooks) AddAfterPing(hook OnAfterPingFunc) { - c.OnAfterPing = append(c.OnAfterPing, hook) -} - -func (c *Hooks) beforePing(ctx context.Context, id any, message *mcp.PingRequest) { - c.beforeAny(ctx, id, mcp.MethodPing, message) - if c == nil { - return - } - for _, hook := range c.OnBeforePing { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterPing(ctx context.Context, id any, message *mcp.PingRequest, result *mcp.EmptyResult) { - c.onSuccess(ctx, id, mcp.MethodPing, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterPing { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforeSetLevel(hook OnBeforeSetLevelFunc) { - c.OnBeforeSetLevel = append(c.OnBeforeSetLevel, hook) -} - -func (c *Hooks) AddAfterSetLevel(hook OnAfterSetLevelFunc) { - c.OnAfterSetLevel = append(c.OnAfterSetLevel, hook) -} - -func (c *Hooks) beforeSetLevel(ctx context.Context, id any, message *mcp.SetLevelRequest) { - c.beforeAny(ctx, id, mcp.MethodSetLogLevel, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeSetLevel { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterSetLevel(ctx context.Context, id any, message *mcp.SetLevelRequest, result *mcp.EmptyResult) { - c.onSuccess(ctx, id, mcp.MethodSetLogLevel, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterSetLevel { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforeListResources(hook OnBeforeListResourcesFunc) { - c.OnBeforeListResources = append(c.OnBeforeListResources, hook) -} - -func (c *Hooks) AddAfterListResources(hook OnAfterListResourcesFunc) { - c.OnAfterListResources = append(c.OnAfterListResources, hook) -} - -func (c *Hooks) beforeListResources(ctx context.Context, id any, message *mcp.ListResourcesRequest) { - c.beforeAny(ctx, id, mcp.MethodResourcesList, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeListResources { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterListResources(ctx context.Context, id any, message *mcp.ListResourcesRequest, result *mcp.ListResourcesResult) { - c.onSuccess(ctx, id, mcp.MethodResourcesList, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterListResources { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforeListResourceTemplates(hook OnBeforeListResourceTemplatesFunc) { - c.OnBeforeListResourceTemplates = append(c.OnBeforeListResourceTemplates, hook) -} - -func (c *Hooks) AddAfterListResourceTemplates(hook OnAfterListResourceTemplatesFunc) { - c.OnAfterListResourceTemplates = append(c.OnAfterListResourceTemplates, hook) -} - -func (c *Hooks) beforeListResourceTemplates(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest) { - c.beforeAny(ctx, id, mcp.MethodResourcesTemplatesList, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeListResourceTemplates { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterListResourceTemplates(ctx context.Context, id any, message *mcp.ListResourceTemplatesRequest, result *mcp.ListResourceTemplatesResult) { - c.onSuccess(ctx, id, mcp.MethodResourcesTemplatesList, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterListResourceTemplates { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforeReadResource(hook OnBeforeReadResourceFunc) { - c.OnBeforeReadResource = append(c.OnBeforeReadResource, hook) -} - -func (c *Hooks) AddAfterReadResource(hook OnAfterReadResourceFunc) { - c.OnAfterReadResource = append(c.OnAfterReadResource, hook) -} - -func (c *Hooks) beforeReadResource(ctx context.Context, id any, message *mcp.ReadResourceRequest) { - c.beforeAny(ctx, id, mcp.MethodResourcesRead, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeReadResource { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterReadResource(ctx context.Context, id any, message *mcp.ReadResourceRequest, result *mcp.ReadResourceResult) { - c.onSuccess(ctx, id, mcp.MethodResourcesRead, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterReadResource { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforeListPrompts(hook OnBeforeListPromptsFunc) { - c.OnBeforeListPrompts = append(c.OnBeforeListPrompts, hook) -} - -func (c *Hooks) AddAfterListPrompts(hook OnAfterListPromptsFunc) { - c.OnAfterListPrompts = append(c.OnAfterListPrompts, hook) -} - -func (c *Hooks) beforeListPrompts(ctx context.Context, id any, message *mcp.ListPromptsRequest) { - c.beforeAny(ctx, id, mcp.MethodPromptsList, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeListPrompts { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterListPrompts(ctx context.Context, id any, message *mcp.ListPromptsRequest, result *mcp.ListPromptsResult) { - c.onSuccess(ctx, id, mcp.MethodPromptsList, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterListPrompts { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforeGetPrompt(hook OnBeforeGetPromptFunc) { - c.OnBeforeGetPrompt = append(c.OnBeforeGetPrompt, hook) -} - -func (c *Hooks) AddAfterGetPrompt(hook OnAfterGetPromptFunc) { - c.OnAfterGetPrompt = append(c.OnAfterGetPrompt, hook) -} - -func (c *Hooks) beforeGetPrompt(ctx context.Context, id any, message *mcp.GetPromptRequest) { - c.beforeAny(ctx, id, mcp.MethodPromptsGet, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeGetPrompt { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterGetPrompt(ctx context.Context, id any, message *mcp.GetPromptRequest, result *mcp.GetPromptResult) { - c.onSuccess(ctx, id, mcp.MethodPromptsGet, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterGetPrompt { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforeListTools(hook OnBeforeListToolsFunc) { - c.OnBeforeListTools = append(c.OnBeforeListTools, hook) -} - -func (c *Hooks) AddAfterListTools(hook OnAfterListToolsFunc) { - c.OnAfterListTools = append(c.OnAfterListTools, hook) -} - -func (c *Hooks) beforeListTools(ctx context.Context, id any, message *mcp.ListToolsRequest) { - c.beforeAny(ctx, id, mcp.MethodToolsList, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeListTools { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterListTools(ctx context.Context, id any, message *mcp.ListToolsRequest, result *mcp.ListToolsResult) { - c.onSuccess(ctx, id, mcp.MethodToolsList, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterListTools { - hook(ctx, id, message, result) - } -} -func (c *Hooks) AddBeforeCallTool(hook OnBeforeCallToolFunc) { - c.OnBeforeCallTool = append(c.OnBeforeCallTool, hook) -} - -func (c *Hooks) AddAfterCallTool(hook OnAfterCallToolFunc) { - c.OnAfterCallTool = append(c.OnAfterCallTool, hook) -} - -func (c *Hooks) beforeCallTool(ctx context.Context, id any, message *mcp.CallToolRequest) { - c.beforeAny(ctx, id, mcp.MethodToolsCall, message) - if c == nil { - return - } - for _, hook := range c.OnBeforeCallTool { - hook(ctx, id, message) - } -} - -func (c *Hooks) afterCallTool(ctx context.Context, id any, message *mcp.CallToolRequest, result *mcp.CallToolResult) { - c.onSuccess(ctx, id, mcp.MethodToolsCall, message, result) - if c == nil { - return - } - for _, hook := range c.OnAfterCallTool { - hook(ctx, id, message, result) - } -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/http_transport_options.go b/vendor/github.com/mark3labs/mcp-go/server/http_transport_options.go deleted file mode 100644 index 4f5ad53d0d..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/http_transport_options.go +++ /dev/null @@ -1,11 +0,0 @@ -package server - -import ( - "context" - "net/http" -) - -// HTTPContextFunc is a function that takes an existing context and the current -// request and returns a potentially modified context based on the request -// content. This can be used to inject context values from headers, for example. -type HTTPContextFunc func(ctx context.Context, r *http.Request) context.Context diff --git a/vendor/github.com/mark3labs/mcp-go/server/request_handler.go b/vendor/github.com/mark3labs/mcp-go/server/request_handler.go deleted file mode 100644 index 25f6ef14f3..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/request_handler.go +++ /dev/null @@ -1,320 +0,0 @@ -// Code generated by `go generate`. DO NOT EDIT. -// source: server/internal/gen/request_handler.go.tmpl -package server - -import ( - "context" - "encoding/json" - "fmt" - - "github.com/mark3labs/mcp-go/mcp" -) - -// HandleMessage processes an incoming JSON-RPC message and returns an appropriate response -func (s *MCPServer) HandleMessage( - ctx context.Context, - message json.RawMessage, -) mcp.JSONRPCMessage { - // Add server to context - ctx = context.WithValue(ctx, serverKey{}, s) - var err *requestError - - var baseMessage struct { - JSONRPC string `json:"jsonrpc"` - Method mcp.MCPMethod `json:"method"` - ID any `json:"id,omitempty"` - Result any `json:"result,omitempty"` - } - - if err := json.Unmarshal(message, &baseMessage); err != nil { - return createErrorResponse( - nil, - mcp.PARSE_ERROR, - "Failed to parse message", - ) - } - - // Check for valid JSONRPC version - if baseMessage.JSONRPC != mcp.JSONRPC_VERSION { - return createErrorResponse( - baseMessage.ID, - mcp.INVALID_REQUEST, - "Invalid JSON-RPC version", - ) - } - - if baseMessage.ID == nil { - var notification mcp.JSONRPCNotification - if err := json.Unmarshal(message, ¬ification); err != nil { - return createErrorResponse( - nil, - mcp.PARSE_ERROR, - "Failed to parse notification", - ) - } - s.handleNotification(ctx, notification) - return nil // Return nil for notifications - } - - if baseMessage.Result != nil { - // this is a response to a request sent by the server (e.g. from a ping - // sent due to WithKeepAlive option) - return nil - } - - handleErr := s.hooks.onRequestInitialization(ctx, baseMessage.ID, message) - if handleErr != nil { - return createErrorResponse( - baseMessage.ID, - mcp.INVALID_REQUEST, - handleErr.Error(), - ) - } - - switch baseMessage.Method { - case mcp.MethodInitialize: - var request mcp.InitializeRequest - var result *mcp.InitializeResult - if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeInitialize(ctx, baseMessage.ID, &request) - result, err = s.handleInitialize(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterInitialize(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodPing: - var request mcp.PingRequest - var result *mcp.EmptyResult - if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforePing(ctx, baseMessage.ID, &request) - result, err = s.handlePing(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterPing(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodSetLogLevel: - var request mcp.SetLevelRequest - var result *mcp.EmptyResult - if s.capabilities.logging == nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.METHOD_NOT_FOUND, - err: fmt.Errorf("logging %w", ErrUnsupported), - } - } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeSetLevel(ctx, baseMessage.ID, &request) - result, err = s.handleSetLevel(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterSetLevel(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodResourcesList: - var request mcp.ListResourcesRequest - var result *mcp.ListResourcesResult - if s.capabilities.resources == nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.METHOD_NOT_FOUND, - err: fmt.Errorf("resources %w", ErrUnsupported), - } - } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeListResources(ctx, baseMessage.ID, &request) - result, err = s.handleListResources(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterListResources(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodResourcesTemplatesList: - var request mcp.ListResourceTemplatesRequest - var result *mcp.ListResourceTemplatesResult - if s.capabilities.resources == nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.METHOD_NOT_FOUND, - err: fmt.Errorf("resources %w", ErrUnsupported), - } - } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeListResourceTemplates(ctx, baseMessage.ID, &request) - result, err = s.handleListResourceTemplates(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterListResourceTemplates(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodResourcesRead: - var request mcp.ReadResourceRequest - var result *mcp.ReadResourceResult - if s.capabilities.resources == nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.METHOD_NOT_FOUND, - err: fmt.Errorf("resources %w", ErrUnsupported), - } - } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeReadResource(ctx, baseMessage.ID, &request) - result, err = s.handleReadResource(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterReadResource(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodPromptsList: - var request mcp.ListPromptsRequest - var result *mcp.ListPromptsResult - if s.capabilities.prompts == nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.METHOD_NOT_FOUND, - err: fmt.Errorf("prompts %w", ErrUnsupported), - } - } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeListPrompts(ctx, baseMessage.ID, &request) - result, err = s.handleListPrompts(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterListPrompts(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodPromptsGet: - var request mcp.GetPromptRequest - var result *mcp.GetPromptResult - if s.capabilities.prompts == nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.METHOD_NOT_FOUND, - err: fmt.Errorf("prompts %w", ErrUnsupported), - } - } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeGetPrompt(ctx, baseMessage.ID, &request) - result, err = s.handleGetPrompt(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterGetPrompt(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodToolsList: - var request mcp.ListToolsRequest - var result *mcp.ListToolsResult - if s.capabilities.tools == nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.METHOD_NOT_FOUND, - err: fmt.Errorf("tools %w", ErrUnsupported), - } - } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeListTools(ctx, baseMessage.ID, &request) - result, err = s.handleListTools(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterListTools(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - case mcp.MethodToolsCall: - var request mcp.CallToolRequest - var result *mcp.CallToolResult - if s.capabilities.tools == nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.METHOD_NOT_FOUND, - err: fmt.Errorf("tools %w", ErrUnsupported), - } - } else if unmarshalErr := json.Unmarshal(message, &request); unmarshalErr != nil { - err = &requestError{ - id: baseMessage.ID, - code: mcp.INVALID_REQUEST, - err: &UnparsableMessageError{message: message, err: unmarshalErr, method: baseMessage.Method}, - } - } else { - s.hooks.beforeCallTool(ctx, baseMessage.ID, &request) - result, err = s.handleToolCall(ctx, baseMessage.ID, request) - } - if err != nil { - s.hooks.onError(ctx, baseMessage.ID, baseMessage.Method, &request, err) - return err.ToJSONRPCError() - } - s.hooks.afterCallTool(ctx, baseMessage.ID, &request, result) - return createResponse(baseMessage.ID, *result) - default: - return createErrorResponse( - baseMessage.ID, - mcp.METHOD_NOT_FOUND, - fmt.Sprintf("Method %s not found", baseMessage.Method), - ) - } -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/sampling.go b/vendor/github.com/mark3labs/mcp-go/server/sampling.go deleted file mode 100644 index b633b24d07..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/sampling.go +++ /dev/null @@ -1,37 +0,0 @@ -package server - -import ( - "context" - "fmt" - - "github.com/mark3labs/mcp-go/mcp" -) - -// EnableSampling enables sampling capabilities for the server. -// This allows the server to send sampling requests to clients that support it. -func (s *MCPServer) EnableSampling() { - s.capabilitiesMu.Lock() - defer s.capabilitiesMu.Unlock() -} - -// RequestSampling sends a sampling request to the client. -// The client must have declared sampling capability during initialization. -func (s *MCPServer) RequestSampling(ctx context.Context, request mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) { - session := ClientSessionFromContext(ctx) - if session == nil { - return nil, fmt.Errorf("no active session") - } - - // Check if the session supports sampling requests - if samplingSession, ok := session.(SessionWithSampling); ok { - return samplingSession.RequestSampling(ctx, request) - } - - return nil, fmt.Errorf("session does not support sampling") -} - -// SessionWithSampling extends ClientSession to support sampling requests. -type SessionWithSampling interface { - ClientSession - RequestSampling(ctx context.Context, request mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/server.go b/vendor/github.com/mark3labs/mcp-go/server/server.go deleted file mode 100644 index 46e6d9c571..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/server.go +++ /dev/null @@ -1,1079 +0,0 @@ -// Package server provides MCP (Model Context Protocol) server implementations. -package server - -import ( - "context" - "encoding/base64" - "encoding/json" - "fmt" - "slices" - "sort" - "sync" - - "github.com/mark3labs/mcp-go/mcp" -) - -// resourceEntry holds both a resource and its handler -type resourceEntry struct { - resource mcp.Resource - handler ResourceHandlerFunc -} - -// resourceTemplateEntry holds both a template and its handler -type resourceTemplateEntry struct { - template mcp.ResourceTemplate - handler ResourceTemplateHandlerFunc -} - -// ServerOption is a function that configures an MCPServer. -type ServerOption func(*MCPServer) - -// ResourceHandlerFunc is a function that returns resource contents. -type ResourceHandlerFunc func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) - -// ResourceTemplateHandlerFunc is a function that returns a resource template. -type ResourceTemplateHandlerFunc func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) - -// PromptHandlerFunc handles prompt requests with given arguments. -type PromptHandlerFunc func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) - -// ToolHandlerFunc handles tool calls with given arguments. -type ToolHandlerFunc func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) - -// ToolHandlerMiddleware is a middleware function that wraps a ToolHandlerFunc. -type ToolHandlerMiddleware func(ToolHandlerFunc) ToolHandlerFunc - -// ToolFilterFunc is a function that filters tools based on context, typically using session information. -type ToolFilterFunc func(ctx context.Context, tools []mcp.Tool) []mcp.Tool - -// ServerTool combines a Tool with its ToolHandlerFunc. -type ServerTool struct { - Tool mcp.Tool - Handler ToolHandlerFunc -} - -// ServerPrompt combines a Prompt with its handler function. -type ServerPrompt struct { - Prompt mcp.Prompt - Handler PromptHandlerFunc -} - -// ServerResource combines a Resource with its handler function. -type ServerResource struct { - Resource mcp.Resource - Handler ResourceHandlerFunc -} - -// serverKey is the context key for storing the server instance -type serverKey struct{} - -// ServerFromContext retrieves the MCPServer instance from a context -func ServerFromContext(ctx context.Context) *MCPServer { - if srv, ok := ctx.Value(serverKey{}).(*MCPServer); ok { - return srv - } - return nil -} - -// UnparsableMessageError is attached to the RequestError when json.Unmarshal -// fails on the request. -type UnparsableMessageError struct { - message json.RawMessage - method mcp.MCPMethod - err error -} - -func (e *UnparsableMessageError) Error() string { - return fmt.Sprintf("unparsable %s request: %s", e.method, e.err) -} - -func (e *UnparsableMessageError) Unwrap() error { - return e.err -} - -func (e *UnparsableMessageError) GetMessage() json.RawMessage { - return e.message -} - -func (e *UnparsableMessageError) GetMethod() mcp.MCPMethod { - return e.method -} - -// RequestError is an error that can be converted to a JSON-RPC error. -// Implements Unwrap() to allow inspecting the error chain. -type requestError struct { - id any - code int - err error -} - -func (e *requestError) Error() string { - return fmt.Sprintf("request error: %s", e.err) -} - -func (e *requestError) ToJSONRPCError() mcp.JSONRPCError { - return mcp.JSONRPCError{ - JSONRPC: mcp.JSONRPC_VERSION, - ID: mcp.NewRequestId(e.id), - Error: struct { - Code int `json:"code"` - Message string `json:"message"` - Data any `json:"data,omitempty"` - }{ - Code: e.code, - Message: e.err.Error(), - }, - } -} - -func (e *requestError) Unwrap() error { - return e.err -} - -// NotificationHandlerFunc handles incoming notifications. -type NotificationHandlerFunc func(ctx context.Context, notification mcp.JSONRPCNotification) - -// MCPServer implements a Model Context Protocol server that can handle various types of requests -// including resources, prompts, and tools. -type MCPServer struct { - // Separate mutexes for different resource types - resourcesMu sync.RWMutex - promptsMu sync.RWMutex - toolsMu sync.RWMutex - middlewareMu sync.RWMutex - notificationHandlersMu sync.RWMutex - capabilitiesMu sync.RWMutex - toolFiltersMu sync.RWMutex - - name string - version string - instructions string - resources map[string]resourceEntry - resourceTemplates map[string]resourceTemplateEntry - prompts map[string]mcp.Prompt - promptHandlers map[string]PromptHandlerFunc - tools map[string]ServerTool - toolHandlerMiddlewares []ToolHandlerMiddleware - toolFilters []ToolFilterFunc - notificationHandlers map[string]NotificationHandlerFunc - capabilities serverCapabilities - paginationLimit *int - sessions sync.Map - hooks *Hooks -} - -// WithPaginationLimit sets the pagination limit for the server. -func WithPaginationLimit(limit int) ServerOption { - return func(s *MCPServer) { - s.paginationLimit = &limit - } -} - -// serverCapabilities defines the supported features of the MCP server -type serverCapabilities struct { - tools *toolCapabilities - resources *resourceCapabilities - prompts *promptCapabilities - logging *bool -} - -// resourceCapabilities defines the supported resource-related features -type resourceCapabilities struct { - subscribe bool - listChanged bool -} - -// promptCapabilities defines the supported prompt-related features -type promptCapabilities struct { - listChanged bool -} - -// toolCapabilities defines the supported tool-related features -type toolCapabilities struct { - listChanged bool -} - -// WithResourceCapabilities configures resource-related server capabilities -func WithResourceCapabilities(subscribe, listChanged bool) ServerOption { - return func(s *MCPServer) { - // Always create a non-nil capability object - s.capabilities.resources = &resourceCapabilities{ - subscribe: subscribe, - listChanged: listChanged, - } - } -} - -// WithToolHandlerMiddleware allows adding a middleware for the -// tool handler call chain. -func WithToolHandlerMiddleware( - toolHandlerMiddleware ToolHandlerMiddleware, -) ServerOption { - return func(s *MCPServer) { - s.middlewareMu.Lock() - s.toolHandlerMiddlewares = append(s.toolHandlerMiddlewares, toolHandlerMiddleware) - s.middlewareMu.Unlock() - } -} - -// WithToolFilter adds a filter function that will be applied to tools before they are returned in list_tools -func WithToolFilter( - toolFilter ToolFilterFunc, -) ServerOption { - return func(s *MCPServer) { - s.toolFiltersMu.Lock() - s.toolFilters = append(s.toolFilters, toolFilter) - s.toolFiltersMu.Unlock() - } -} - -// WithRecovery adds a middleware that recovers from panics in tool handlers. -func WithRecovery() ServerOption { - return WithToolHandlerMiddleware(func(next ToolHandlerFunc) ToolHandlerFunc { - return func(ctx context.Context, request mcp.CallToolRequest) (result *mcp.CallToolResult, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf( - "panic recovered in %s tool handler: %v", - request.Params.Name, - r, - ) - } - }() - return next(ctx, request) - } - }) -} - -// WithHooks allows adding hooks that will be called before or after -// either [all] requests or before / after specific request methods, or else -// prior to returning an error to the client. -func WithHooks(hooks *Hooks) ServerOption { - return func(s *MCPServer) { - s.hooks = hooks - } -} - -// WithPromptCapabilities configures prompt-related server capabilities -func WithPromptCapabilities(listChanged bool) ServerOption { - return func(s *MCPServer) { - // Always create a non-nil capability object - s.capabilities.prompts = &promptCapabilities{ - listChanged: listChanged, - } - } -} - -// WithToolCapabilities configures tool-related server capabilities -func WithToolCapabilities(listChanged bool) ServerOption { - return func(s *MCPServer) { - // Always create a non-nil capability object - s.capabilities.tools = &toolCapabilities{ - listChanged: listChanged, - } - } -} - -// WithLogging enables logging capabilities for the server -func WithLogging() ServerOption { - return func(s *MCPServer) { - s.capabilities.logging = mcp.ToBoolPtr(true) - } -} - -// WithInstructions sets the server instructions for the client returned in the initialize response -func WithInstructions(instructions string) ServerOption { - return func(s *MCPServer) { - s.instructions = instructions - } -} - -// NewMCPServer creates a new MCP server instance with the given name, version and options -func NewMCPServer( - name, version string, - opts ...ServerOption, -) *MCPServer { - s := &MCPServer{ - resources: make(map[string]resourceEntry), - resourceTemplates: make(map[string]resourceTemplateEntry), - prompts: make(map[string]mcp.Prompt), - promptHandlers: make(map[string]PromptHandlerFunc), - tools: make(map[string]ServerTool), - name: name, - version: version, - notificationHandlers: make(map[string]NotificationHandlerFunc), - capabilities: serverCapabilities{ - tools: nil, - resources: nil, - prompts: nil, - logging: nil, - }, - } - - for _, opt := range opts { - opt(s) - } - - return s -} - -// AddResources registers multiple resources at once -func (s *MCPServer) AddResources(resources ...ServerResource) { - s.implicitlyRegisterResourceCapabilities() - - s.resourcesMu.Lock() - for _, entry := range resources { - s.resources[entry.Resource.URI] = resourceEntry{ - resource: entry.Resource, - handler: entry.Handler, - } - } - s.resourcesMu.Unlock() - - // When the list of available resources changes, servers that declared the listChanged capability SHOULD send a notification - if s.capabilities.resources.listChanged { - // Send notification to all initialized sessions - s.SendNotificationToAllClients(mcp.MethodNotificationResourcesListChanged, nil) - } -} - -// AddResource registers a new resource and its handler -func (s *MCPServer) AddResource( - resource mcp.Resource, - handler ResourceHandlerFunc, -) { - s.AddResources(ServerResource{Resource: resource, Handler: handler}) -} - -// RemoveResource removes a resource from the server -func (s *MCPServer) RemoveResource(uri string) { - s.resourcesMu.Lock() - _, exists := s.resources[uri] - if exists { - delete(s.resources, uri) - } - s.resourcesMu.Unlock() - - // Send notification to all initialized sessions if listChanged capability is enabled and we actually remove a resource - if exists && s.capabilities.resources != nil && s.capabilities.resources.listChanged { - s.SendNotificationToAllClients(mcp.MethodNotificationResourcesListChanged, nil) - } -} - -// AddResourceTemplate registers a new resource template and its handler -func (s *MCPServer) AddResourceTemplate( - template mcp.ResourceTemplate, - handler ResourceTemplateHandlerFunc, -) { - s.implicitlyRegisterResourceCapabilities() - - s.resourcesMu.Lock() - s.resourceTemplates[template.URITemplate.Raw()] = resourceTemplateEntry{ - template: template, - handler: handler, - } - s.resourcesMu.Unlock() - - // When the list of available resources changes, servers that declared the listChanged capability SHOULD send a notification - if s.capabilities.resources.listChanged { - // Send notification to all initialized sessions - s.SendNotificationToAllClients(mcp.MethodNotificationResourcesListChanged, nil) - } -} - -// AddPrompts registers multiple prompts at once -func (s *MCPServer) AddPrompts(prompts ...ServerPrompt) { - s.implicitlyRegisterPromptCapabilities() - - s.promptsMu.Lock() - for _, entry := range prompts { - s.prompts[entry.Prompt.Name] = entry.Prompt - s.promptHandlers[entry.Prompt.Name] = entry.Handler - } - s.promptsMu.Unlock() - - // When the list of available prompts changes, servers that declared the listChanged capability SHOULD send a notification. - if s.capabilities.prompts.listChanged { - // Send notification to all initialized sessions - s.SendNotificationToAllClients(mcp.MethodNotificationPromptsListChanged, nil) - } -} - -// AddPrompt registers a new prompt handler with the given name -func (s *MCPServer) AddPrompt(prompt mcp.Prompt, handler PromptHandlerFunc) { - s.AddPrompts(ServerPrompt{Prompt: prompt, Handler: handler}) -} - -// DeletePrompts removes prompts from the server -func (s *MCPServer) DeletePrompts(names ...string) { - s.promptsMu.Lock() - var exists bool - for _, name := range names { - if _, ok := s.prompts[name]; ok { - delete(s.prompts, name) - delete(s.promptHandlers, name) - exists = true - } - } - s.promptsMu.Unlock() - - // Send notification to all initialized sessions if listChanged capability is enabled, and we actually remove a prompt - if exists && s.capabilities.prompts != nil && s.capabilities.prompts.listChanged { - // Send notification to all initialized sessions - s.SendNotificationToAllClients(mcp.MethodNotificationPromptsListChanged, nil) - } -} - -// AddTool registers a new tool and its handler -func (s *MCPServer) AddTool(tool mcp.Tool, handler ToolHandlerFunc) { - s.AddTools(ServerTool{Tool: tool, Handler: handler}) -} - -// Register tool capabilities due to a tool being added. Default to -// listChanged: true, but don't change the value if we've already explicitly -// registered tools.listChanged false. -func (s *MCPServer) implicitlyRegisterToolCapabilities() { - s.implicitlyRegisterCapabilities( - func() bool { return s.capabilities.tools != nil }, - func() { s.capabilities.tools = &toolCapabilities{listChanged: true} }, - ) -} - -func (s *MCPServer) implicitlyRegisterResourceCapabilities() { - s.implicitlyRegisterCapabilities( - func() bool { return s.capabilities.resources != nil }, - func() { s.capabilities.resources = &resourceCapabilities{} }, - ) -} - -func (s *MCPServer) implicitlyRegisterPromptCapabilities() { - s.implicitlyRegisterCapabilities( - func() bool { return s.capabilities.prompts != nil }, - func() { s.capabilities.prompts = &promptCapabilities{} }, - ) -} - -func (s *MCPServer) implicitlyRegisterCapabilities(check func() bool, register func()) { - s.capabilitiesMu.RLock() - if check() { - s.capabilitiesMu.RUnlock() - return - } - s.capabilitiesMu.RUnlock() - - s.capabilitiesMu.Lock() - if !check() { - register() - } - s.capabilitiesMu.Unlock() -} - -// AddTools registers multiple tools at once -func (s *MCPServer) AddTools(tools ...ServerTool) { - s.implicitlyRegisterToolCapabilities() - - s.toolsMu.Lock() - for _, entry := range tools { - s.tools[entry.Tool.Name] = entry - } - s.toolsMu.Unlock() - - // When the list of available tools changes, servers that declared the listChanged capability SHOULD send a notification. - if s.capabilities.tools.listChanged { - // Send notification to all initialized sessions - s.SendNotificationToAllClients(mcp.MethodNotificationToolsListChanged, nil) - } -} - -// SetTools replaces all existing tools with the provided list -func (s *MCPServer) SetTools(tools ...ServerTool) { - s.toolsMu.Lock() - s.tools = make(map[string]ServerTool, len(tools)) - s.toolsMu.Unlock() - s.AddTools(tools...) -} - -// DeleteTools removes tools from the server -func (s *MCPServer) DeleteTools(names ...string) { - s.toolsMu.Lock() - var exists bool - for _, name := range names { - if _, ok := s.tools[name]; ok { - delete(s.tools, name) - exists = true - } - } - s.toolsMu.Unlock() - - // When the list of available tools changes, servers that declared the listChanged capability SHOULD send a notification. - if exists && s.capabilities.tools != nil && s.capabilities.tools.listChanged { - // Send notification to all initialized sessions - s.SendNotificationToAllClients(mcp.MethodNotificationToolsListChanged, nil) - } -} - -// AddNotificationHandler registers a new handler for incoming notifications -func (s *MCPServer) AddNotificationHandler( - method string, - handler NotificationHandlerFunc, -) { - s.notificationHandlersMu.Lock() - defer s.notificationHandlersMu.Unlock() - s.notificationHandlers[method] = handler -} - -func (s *MCPServer) handleInitialize( - ctx context.Context, - _ any, - request mcp.InitializeRequest, -) (*mcp.InitializeResult, *requestError) { - capabilities := mcp.ServerCapabilities{} - - // Only add resource capabilities if they're configured - if s.capabilities.resources != nil { - capabilities.Resources = &struct { - Subscribe bool `json:"subscribe,omitempty"` - ListChanged bool `json:"listChanged,omitempty"` - }{ - Subscribe: s.capabilities.resources.subscribe, - ListChanged: s.capabilities.resources.listChanged, - } - } - - // Only add prompt capabilities if they're configured - if s.capabilities.prompts != nil { - capabilities.Prompts = &struct { - ListChanged bool `json:"listChanged,omitempty"` - }{ - ListChanged: s.capabilities.prompts.listChanged, - } - } - - // Only add tool capabilities if they're configured - if s.capabilities.tools != nil { - capabilities.Tools = &struct { - ListChanged bool `json:"listChanged,omitempty"` - }{ - ListChanged: s.capabilities.tools.listChanged, - } - } - - if s.capabilities.logging != nil && *s.capabilities.logging { - capabilities.Logging = &struct{}{} - } - - result := mcp.InitializeResult{ - ProtocolVersion: s.protocolVersion(request.Params.ProtocolVersion), - ServerInfo: mcp.Implementation{ - Name: s.name, - Version: s.version, - }, - Capabilities: capabilities, - Instructions: s.instructions, - } - - if session := ClientSessionFromContext(ctx); session != nil { - session.Initialize() - - // Store client info if the session supports it - if sessionWithClientInfo, ok := session.(SessionWithClientInfo); ok { - sessionWithClientInfo.SetClientInfo(request.Params.ClientInfo) - } - } - return &result, nil -} - -func (s *MCPServer) protocolVersion(clientVersion string) string { - if slices.Contains(mcp.ValidProtocolVersions, clientVersion) { - return clientVersion - } - - return mcp.LATEST_PROTOCOL_VERSION -} - -func (s *MCPServer) handlePing( - _ context.Context, - _ any, - _ mcp.PingRequest, -) (*mcp.EmptyResult, *requestError) { - return &mcp.EmptyResult{}, nil -} - -func (s *MCPServer) handleSetLevel( - ctx context.Context, - id any, - request mcp.SetLevelRequest, -) (*mcp.EmptyResult, *requestError) { - clientSession := ClientSessionFromContext(ctx) - if clientSession == nil || !clientSession.Initialized() { - return nil, &requestError{ - id: id, - code: mcp.INTERNAL_ERROR, - err: ErrSessionNotInitialized, - } - } - - sessionLogging, ok := clientSession.(SessionWithLogging) - if !ok { - return nil, &requestError{ - id: id, - code: mcp.INTERNAL_ERROR, - err: ErrSessionDoesNotSupportLogging, - } - } - - level := request.Params.Level - // Validate logging level - switch level { - case mcp.LoggingLevelDebug, mcp.LoggingLevelInfo, mcp.LoggingLevelNotice, - mcp.LoggingLevelWarning, mcp.LoggingLevelError, mcp.LoggingLevelCritical, - mcp.LoggingLevelAlert, mcp.LoggingLevelEmergency: - // Valid level - default: - return nil, &requestError{ - id: id, - code: mcp.INVALID_PARAMS, - err: fmt.Errorf("invalid logging level '%s'", level), - } - } - - sessionLogging.SetLogLevel(level) - - return &mcp.EmptyResult{}, nil -} - -func listByPagination[T mcp.Named]( - _ context.Context, - s *MCPServer, - cursor mcp.Cursor, - allElements []T, -) ([]T, mcp.Cursor, error) { - startPos := 0 - if cursor != "" { - c, err := base64.StdEncoding.DecodeString(string(cursor)) - if err != nil { - return nil, "", err - } - cString := string(c) - startPos = sort.Search(len(allElements), func(i int) bool { - return allElements[i].GetName() > cString - }) - } - endPos := len(allElements) - if s.paginationLimit != nil { - if len(allElements) > startPos+*s.paginationLimit { - endPos = startPos + *s.paginationLimit - } - } - elementsToReturn := allElements[startPos:endPos] - // set the next cursor - nextCursor := func() mcp.Cursor { - if s.paginationLimit != nil && len(elementsToReturn) >= *s.paginationLimit { - nc := elementsToReturn[len(elementsToReturn)-1].GetName() - toString := base64.StdEncoding.EncodeToString([]byte(nc)) - return mcp.Cursor(toString) - } - return "" - }() - return elementsToReturn, nextCursor, nil -} - -func (s *MCPServer) handleListResources( - ctx context.Context, - id any, - request mcp.ListResourcesRequest, -) (*mcp.ListResourcesResult, *requestError) { - s.resourcesMu.RLock() - resources := make([]mcp.Resource, 0, len(s.resources)) - for _, entry := range s.resources { - resources = append(resources, entry.resource) - } - s.resourcesMu.RUnlock() - - // Sort the resources by name - sort.Slice(resources, func(i, j int) bool { - return resources[i].Name < resources[j].Name - }) - resourcesToReturn, nextCursor, err := listByPagination( - ctx, - s, - request.Params.Cursor, - resources, - ) - if err != nil { - return nil, &requestError{ - id: id, - code: mcp.INVALID_PARAMS, - err: err, - } - } - result := mcp.ListResourcesResult{ - Resources: resourcesToReturn, - PaginatedResult: mcp.PaginatedResult{ - NextCursor: nextCursor, - }, - } - return &result, nil -} - -func (s *MCPServer) handleListResourceTemplates( - ctx context.Context, - id any, - request mcp.ListResourceTemplatesRequest, -) (*mcp.ListResourceTemplatesResult, *requestError) { - s.resourcesMu.RLock() - templates := make([]mcp.ResourceTemplate, 0, len(s.resourceTemplates)) - for _, entry := range s.resourceTemplates { - templates = append(templates, entry.template) - } - s.resourcesMu.RUnlock() - sort.Slice(templates, func(i, j int) bool { - return templates[i].Name < templates[j].Name - }) - templatesToReturn, nextCursor, err := listByPagination( - ctx, - s, - request.Params.Cursor, - templates, - ) - if err != nil { - return nil, &requestError{ - id: id, - code: mcp.INVALID_PARAMS, - err: err, - } - } - result := mcp.ListResourceTemplatesResult{ - ResourceTemplates: templatesToReturn, - PaginatedResult: mcp.PaginatedResult{ - NextCursor: nextCursor, - }, - } - return &result, nil -} - -func (s *MCPServer) handleReadResource( - ctx context.Context, - id any, - request mcp.ReadResourceRequest, -) (*mcp.ReadResourceResult, *requestError) { - s.resourcesMu.RLock() - // First try direct resource handlers - if entry, ok := s.resources[request.Params.URI]; ok { - handler := entry.handler - s.resourcesMu.RUnlock() - contents, err := handler(ctx, request) - if err != nil { - return nil, &requestError{ - id: id, - code: mcp.INTERNAL_ERROR, - err: err, - } - } - return &mcp.ReadResourceResult{Contents: contents}, nil - } - - // If no direct handler found, try matching against templates - var matchedHandler ResourceTemplateHandlerFunc - var matched bool - for _, entry := range s.resourceTemplates { - template := entry.template - if matchesTemplate(request.Params.URI, template.URITemplate) { - matchedHandler = entry.handler - matched = true - matchedVars := template.URITemplate.Match(request.Params.URI) - // Convert matched variables to a map - request.Params.Arguments = make(map[string]any, len(matchedVars)) - for name, value := range matchedVars { - request.Params.Arguments[name] = value.V - } - break - } - } - s.resourcesMu.RUnlock() - - if matched { - contents, err := matchedHandler(ctx, request) - if err != nil { - return nil, &requestError{ - id: id, - code: mcp.INTERNAL_ERROR, - err: err, - } - } - return &mcp.ReadResourceResult{Contents: contents}, nil - } - - return nil, &requestError{ - id: id, - code: mcp.RESOURCE_NOT_FOUND, - err: fmt.Errorf( - "handler not found for resource URI '%s': %w", - request.Params.URI, - ErrResourceNotFound, - ), - } -} - -// matchesTemplate checks if a URI matches a URI template pattern -func matchesTemplate(uri string, template *mcp.URITemplate) bool { - return template.Regexp().MatchString(uri) -} - -func (s *MCPServer) handleListPrompts( - ctx context.Context, - id any, - request mcp.ListPromptsRequest, -) (*mcp.ListPromptsResult, *requestError) { - s.promptsMu.RLock() - prompts := make([]mcp.Prompt, 0, len(s.prompts)) - for _, prompt := range s.prompts { - prompts = append(prompts, prompt) - } - s.promptsMu.RUnlock() - - // sort prompts by name - sort.Slice(prompts, func(i, j int) bool { - return prompts[i].Name < prompts[j].Name - }) - promptsToReturn, nextCursor, err := listByPagination( - ctx, - s, - request.Params.Cursor, - prompts, - ) - if err != nil { - return nil, &requestError{ - id: id, - code: mcp.INVALID_PARAMS, - err: err, - } - } - result := mcp.ListPromptsResult{ - Prompts: promptsToReturn, - PaginatedResult: mcp.PaginatedResult{ - NextCursor: nextCursor, - }, - } - return &result, nil -} - -func (s *MCPServer) handleGetPrompt( - ctx context.Context, - id any, - request mcp.GetPromptRequest, -) (*mcp.GetPromptResult, *requestError) { - s.promptsMu.RLock() - handler, ok := s.promptHandlers[request.Params.Name] - s.promptsMu.RUnlock() - - if !ok { - return nil, &requestError{ - id: id, - code: mcp.INVALID_PARAMS, - err: fmt.Errorf("prompt '%s' not found: %w", request.Params.Name, ErrPromptNotFound), - } - } - - result, err := handler(ctx, request) - if err != nil { - return nil, &requestError{ - id: id, - code: mcp.INTERNAL_ERROR, - err: err, - } - } - - return result, nil -} - -func (s *MCPServer) handleListTools( - ctx context.Context, - id any, - request mcp.ListToolsRequest, -) (*mcp.ListToolsResult, *requestError) { - // Get the base tools from the server - s.toolsMu.RLock() - tools := make([]mcp.Tool, 0, len(s.tools)) - - // Get all tool names for consistent ordering - toolNames := make([]string, 0, len(s.tools)) - for name := range s.tools { - toolNames = append(toolNames, name) - } - - // Sort the tool names for consistent ordering - sort.Strings(toolNames) - - // Add tools in sorted order - for _, name := range toolNames { - tools = append(tools, s.tools[name].Tool) - } - s.toolsMu.RUnlock() - - // Check if there are session-specific tools - session := ClientSessionFromContext(ctx) - if session != nil { - if sessionWithTools, ok := session.(SessionWithTools); ok { - if sessionTools := sessionWithTools.GetSessionTools(); sessionTools != nil { - // Override or add session-specific tools - // We need to create a map first to merge the tools properly - toolMap := make(map[string]mcp.Tool) - - // Add global tools first - for _, tool := range tools { - toolMap[tool.Name] = tool - } - - // Then override with session-specific tools - for name, serverTool := range sessionTools { - toolMap[name] = serverTool.Tool - } - - // Convert back to slice - tools = make([]mcp.Tool, 0, len(toolMap)) - for _, tool := range toolMap { - tools = append(tools, tool) - } - - // Sort again to maintain consistent ordering - sort.Slice(tools, func(i, j int) bool { - return tools[i].Name < tools[j].Name - }) - } - } - } - - // Apply tool filters if any are defined - s.toolFiltersMu.RLock() - if len(s.toolFilters) > 0 { - for _, filter := range s.toolFilters { - tools = filter(ctx, tools) - } - } - s.toolFiltersMu.RUnlock() - - // Apply pagination - toolsToReturn, nextCursor, err := listByPagination( - ctx, - s, - request.Params.Cursor, - tools, - ) - if err != nil { - return nil, &requestError{ - id: id, - code: mcp.INVALID_PARAMS, - err: err, - } - } - - result := mcp.ListToolsResult{ - Tools: toolsToReturn, - PaginatedResult: mcp.PaginatedResult{ - NextCursor: nextCursor, - }, - } - return &result, nil -} - -func (s *MCPServer) handleToolCall( - ctx context.Context, - id any, - request mcp.CallToolRequest, -) (*mcp.CallToolResult, *requestError) { - // First check session-specific tools - var tool ServerTool - var ok bool - - session := ClientSessionFromContext(ctx) - if session != nil { - if sessionWithTools, typeAssertOk := session.(SessionWithTools); typeAssertOk { - if sessionTools := sessionWithTools.GetSessionTools(); sessionTools != nil { - var sessionOk bool - tool, sessionOk = sessionTools[request.Params.Name] - if sessionOk { - ok = true - } - } - } - } - - // If not found in session tools, check global tools - if !ok { - s.toolsMu.RLock() - tool, ok = s.tools[request.Params.Name] - s.toolsMu.RUnlock() - } - - if !ok { - return nil, &requestError{ - id: id, - code: mcp.INVALID_PARAMS, - err: fmt.Errorf("tool '%s' not found: %w", request.Params.Name, ErrToolNotFound), - } - } - - finalHandler := tool.Handler - - s.middlewareMu.RLock() - mw := s.toolHandlerMiddlewares - s.middlewareMu.RUnlock() - - // Apply middlewares in reverse order - for i := len(mw) - 1; i >= 0; i-- { - finalHandler = mw[i](finalHandler) - } - - result, err := finalHandler(ctx, request) - if err != nil { - return nil, &requestError{ - id: id, - code: mcp.INTERNAL_ERROR, - err: err, - } - } - - return result, nil -} - -func (s *MCPServer) handleNotification( - ctx context.Context, - notification mcp.JSONRPCNotification, -) mcp.JSONRPCMessage { - s.notificationHandlersMu.RLock() - handler, ok := s.notificationHandlers[notification.Method] - s.notificationHandlersMu.RUnlock() - - if ok { - handler(ctx, notification) - } - return nil -} - -func createResponse(id any, result any) mcp.JSONRPCMessage { - return mcp.JSONRPCResponse{ - JSONRPC: mcp.JSONRPC_VERSION, - ID: mcp.NewRequestId(id), - Result: result, - } -} - -func createErrorResponse( - id any, - code int, - message string, -) mcp.JSONRPCMessage { - return mcp.JSONRPCError{ - JSONRPC: mcp.JSONRPC_VERSION, - ID: mcp.NewRequestId(id), - Error: struct { - Code int `json:"code"` - Message string `json:"message"` - Data any `json:"data,omitempty"` - }{ - Code: code, - Message: message, - }, - } -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/session.go b/vendor/github.com/mark3labs/mcp-go/server/session.go deleted file mode 100644 index a79da22cad..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/session.go +++ /dev/null @@ -1,380 +0,0 @@ -package server - -import ( - "context" - "fmt" - - "github.com/mark3labs/mcp-go/mcp" -) - -// ClientSession represents an active session that can be used by MCPServer to interact with client. -type ClientSession interface { - // Initialize marks session as fully initialized and ready for notifications - Initialize() - // Initialized returns if session is ready to accept notifications - Initialized() bool - // NotificationChannel provides a channel suitable for sending notifications to client. - NotificationChannel() chan<- mcp.JSONRPCNotification - // SessionID is a unique identifier used to track user session. - SessionID() string -} - -// SessionWithLogging is an extension of ClientSession that can receive log message notifications and set log level -type SessionWithLogging interface { - ClientSession - // SetLogLevel sets the minimum log level - SetLogLevel(level mcp.LoggingLevel) - // GetLogLevel retrieves the minimum log level - GetLogLevel() mcp.LoggingLevel -} - -// SessionWithTools is an extension of ClientSession that can store session-specific tool data -type SessionWithTools interface { - ClientSession - // GetSessionTools returns the tools specific to this session, if any - // This method must be thread-safe for concurrent access - GetSessionTools() map[string]ServerTool - // SetSessionTools sets tools specific to this session - // This method must be thread-safe for concurrent access - SetSessionTools(tools map[string]ServerTool) -} - -// SessionWithClientInfo is an extension of ClientSession that can store client info -type SessionWithClientInfo interface { - ClientSession - // GetClientInfo returns the client information for this session - GetClientInfo() mcp.Implementation - // SetClientInfo sets the client information for this session - SetClientInfo(clientInfo mcp.Implementation) -} - -// SessionWithStreamableHTTPConfig extends ClientSession to support streamable HTTP transport configurations -type SessionWithStreamableHTTPConfig interface { - ClientSession - // UpgradeToSSEWhenReceiveNotification upgrades the client-server communication to SSE stream when the server - // sends notifications to the client - // - // The protocol specification: - // - If the server response contains any JSON-RPC notifications, it MUST either: - // - Return Content-Type: text/event-stream to initiate an SSE stream, OR - // - Return Content-Type: application/json for a single JSON object - // - The client MUST support both response types. - // - // Reference: https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#sending-messages-to-the-server - UpgradeToSSEWhenReceiveNotification() -} - -// clientSessionKey is the context key for storing current client notification channel. -type clientSessionKey struct{} - -// ClientSessionFromContext retrieves current client notification context from context. -func ClientSessionFromContext(ctx context.Context) ClientSession { - if session, ok := ctx.Value(clientSessionKey{}).(ClientSession); ok { - return session - } - return nil -} - -// WithContext sets the current client session and returns the provided context -func (s *MCPServer) WithContext( - ctx context.Context, - session ClientSession, -) context.Context { - return context.WithValue(ctx, clientSessionKey{}, session) -} - -// RegisterSession saves session that should be notified in case if some server attributes changed. -func (s *MCPServer) RegisterSession( - ctx context.Context, - session ClientSession, -) error { - sessionID := session.SessionID() - if _, exists := s.sessions.LoadOrStore(sessionID, session); exists { - return ErrSessionExists - } - s.hooks.RegisterSession(ctx, session) - return nil -} - -// UnregisterSession removes from storage session that is shut down. -func (s *MCPServer) UnregisterSession( - ctx context.Context, - sessionID string, -) { - sessionValue, ok := s.sessions.LoadAndDelete(sessionID) - if !ok { - return - } - if session, ok := sessionValue.(ClientSession); ok { - s.hooks.UnregisterSession(ctx, session) - } -} - -// SendNotificationToAllClients sends a notification to all the currently active clients. -func (s *MCPServer) SendNotificationToAllClients( - method string, - params map[string]any, -) { - notification := mcp.JSONRPCNotification{ - JSONRPC: mcp.JSONRPC_VERSION, - Notification: mcp.Notification{ - Method: method, - Params: mcp.NotificationParams{ - AdditionalFields: params, - }, - }, - } - - s.sessions.Range(func(k, v any) bool { - if session, ok := v.(ClientSession); ok && session.Initialized() { - select { - case session.NotificationChannel() <- notification: - // Successfully sent notification - default: - // Channel is blocked, if there's an error hook, use it - if s.hooks != nil && len(s.hooks.OnError) > 0 { - err := ErrNotificationChannelBlocked - // Copy hooks pointer to local variable to avoid race condition - hooks := s.hooks - go func(sessionID string, hooks *Hooks) { - ctx := context.Background() - // Use the error hook to report the blocked channel - hooks.onError(ctx, nil, "notification", map[string]any{ - "method": method, - "sessionID": sessionID, - }, fmt.Errorf("notification channel blocked for session %s: %w", sessionID, err)) - }(session.SessionID(), hooks) - } - } - } - return true - }) -} - -// SendNotificationToClient sends a notification to the current client -func (s *MCPServer) SendNotificationToClient( - ctx context.Context, - method string, - params map[string]any, -) error { - session := ClientSessionFromContext(ctx) - if session == nil || !session.Initialized() { - return ErrNotificationNotInitialized - } - - // upgrades the client-server communication to SSE stream when the server sends notifications to the client - if sessionWithStreamableHTTPConfig, ok := session.(SessionWithStreamableHTTPConfig); ok { - sessionWithStreamableHTTPConfig.UpgradeToSSEWhenReceiveNotification() - } - - notification := mcp.JSONRPCNotification{ - JSONRPC: mcp.JSONRPC_VERSION, - Notification: mcp.Notification{ - Method: method, - Params: mcp.NotificationParams{ - AdditionalFields: params, - }, - }, - } - - select { - case session.NotificationChannel() <- notification: - return nil - default: - // Channel is blocked, if there's an error hook, use it - if s.hooks != nil && len(s.hooks.OnError) > 0 { - err := ErrNotificationChannelBlocked - // Copy hooks pointer to local variable to avoid race condition - hooks := s.hooks - go func(sessionID string, hooks *Hooks) { - // Use the error hook to report the blocked channel - hooks.onError(ctx, nil, "notification", map[string]any{ - "method": method, - "sessionID": sessionID, - }, fmt.Errorf("notification channel blocked for session %s: %w", sessionID, err)) - }(session.SessionID(), hooks) - } - return ErrNotificationChannelBlocked - } -} - -// SendNotificationToSpecificClient sends a notification to a specific client by session ID -func (s *MCPServer) SendNotificationToSpecificClient( - sessionID string, - method string, - params map[string]any, -) error { - sessionValue, ok := s.sessions.Load(sessionID) - if !ok { - return ErrSessionNotFound - } - - session, ok := sessionValue.(ClientSession) - if !ok || !session.Initialized() { - return ErrSessionNotInitialized - } - - // upgrades the client-server communication to SSE stream when the server sends notifications to the client - if sessionWithStreamableHTTPConfig, ok := session.(SessionWithStreamableHTTPConfig); ok { - sessionWithStreamableHTTPConfig.UpgradeToSSEWhenReceiveNotification() - } - - notification := mcp.JSONRPCNotification{ - JSONRPC: mcp.JSONRPC_VERSION, - Notification: mcp.Notification{ - Method: method, - Params: mcp.NotificationParams{ - AdditionalFields: params, - }, - }, - } - - select { - case session.NotificationChannel() <- notification: - return nil - default: - // Channel is blocked, if there's an error hook, use it - if s.hooks != nil && len(s.hooks.OnError) > 0 { - err := ErrNotificationChannelBlocked - ctx := context.Background() - // Copy hooks pointer to local variable to avoid race condition - hooks := s.hooks - go func(sID string, hooks *Hooks) { - // Use the error hook to report the blocked channel - hooks.onError(ctx, nil, "notification", map[string]any{ - "method": method, - "sessionID": sID, - }, fmt.Errorf("notification channel blocked for session %s: %w", sID, err)) - }(sessionID, hooks) - } - return ErrNotificationChannelBlocked - } -} - -// AddSessionTool adds a tool for a specific session -func (s *MCPServer) AddSessionTool(sessionID string, tool mcp.Tool, handler ToolHandlerFunc) error { - return s.AddSessionTools(sessionID, ServerTool{Tool: tool, Handler: handler}) -} - -// AddSessionTools adds tools for a specific session -func (s *MCPServer) AddSessionTools(sessionID string, tools ...ServerTool) error { - sessionValue, ok := s.sessions.Load(sessionID) - if !ok { - return ErrSessionNotFound - } - - session, ok := sessionValue.(SessionWithTools) - if !ok { - return ErrSessionDoesNotSupportTools - } - - s.implicitlyRegisterToolCapabilities() - - // Get existing tools (this should return a thread-safe copy) - sessionTools := session.GetSessionTools() - - // Create a new map to avoid concurrent modification issues - newSessionTools := make(map[string]ServerTool, len(sessionTools)+len(tools)) - - // Copy existing tools - for k, v := range sessionTools { - newSessionTools[k] = v - } - - // Add new tools - for _, tool := range tools { - newSessionTools[tool.Tool.Name] = tool - } - - // Set the tools (this should be thread-safe) - session.SetSessionTools(newSessionTools) - - // It only makes sense to send tool notifications to initialized sessions -- - // if we're not initialized yet the client can't possibly have sent their - // initial tools/list message. - // - // For initialized sessions, honor tools.listChanged, which is specifically - // about whether notifications will be sent or not. - // see - if session.Initialized() && s.capabilities.tools != nil && s.capabilities.tools.listChanged { - // Send notification only to this session - if err := s.SendNotificationToSpecificClient(sessionID, "notifications/tools/list_changed", nil); err != nil { - // Log the error but don't fail the operation - // The tools were successfully added, but notification failed - if s.hooks != nil && len(s.hooks.OnError) > 0 { - hooks := s.hooks - go func(sID string, hooks *Hooks) { - ctx := context.Background() - hooks.onError(ctx, nil, "notification", map[string]any{ - "method": "notifications/tools/list_changed", - "sessionID": sID, - }, fmt.Errorf("failed to send notification after adding tools: %w", err)) - }(sessionID, hooks) - } - } - } - - return nil -} - -// DeleteSessionTools removes tools from a specific session -func (s *MCPServer) DeleteSessionTools(sessionID string, names ...string) error { - sessionValue, ok := s.sessions.Load(sessionID) - if !ok { - return ErrSessionNotFound - } - - session, ok := sessionValue.(SessionWithTools) - if !ok { - return ErrSessionDoesNotSupportTools - } - - // Get existing tools (this should return a thread-safe copy) - sessionTools := session.GetSessionTools() - if sessionTools == nil { - return nil - } - - // Create a new map to avoid concurrent modification issues - newSessionTools := make(map[string]ServerTool, len(sessionTools)) - - // Copy existing tools except those being deleted - for k, v := range sessionTools { - newSessionTools[k] = v - } - - // Remove specified tools - for _, name := range names { - delete(newSessionTools, name) - } - - // Set the tools (this should be thread-safe) - session.SetSessionTools(newSessionTools) - - // It only makes sense to send tool notifications to initialized sessions -- - // if we're not initialized yet the client can't possibly have sent their - // initial tools/list message. - // - // For initialized sessions, honor tools.listChanged, which is specifically - // about whether notifications will be sent or not. - // see - if session.Initialized() && s.capabilities.tools != nil && s.capabilities.tools.listChanged { - // Send notification only to this session - if err := s.SendNotificationToSpecificClient(sessionID, "notifications/tools/list_changed", nil); err != nil { - // Log the error but don't fail the operation - // The tools were successfully deleted, but notification failed - if s.hooks != nil && len(s.hooks.OnError) > 0 { - hooks := s.hooks - go func(sID string, hooks *Hooks) { - ctx := context.Background() - hooks.onError(ctx, nil, "notification", map[string]any{ - "method": "notifications/tools/list_changed", - "sessionID": sID, - }, fmt.Errorf("failed to send notification after deleting tools: %w", err)) - }(sessionID, hooks) - } - } - } - - return nil -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/sse.go b/vendor/github.com/mark3labs/mcp-go/server/sse.go deleted file mode 100644 index 4169957307..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/sse.go +++ /dev/null @@ -1,736 +0,0 @@ -package server - -import ( - "context" - "encoding/json" - "fmt" - "log" - "net/http" - "net/http/httptest" - "net/url" - "path" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/google/uuid" - - "github.com/mark3labs/mcp-go/mcp" -) - -// sseSession represents an active SSE connection. -type sseSession struct { - done chan struct{} - eventQueue chan string // Channel for queuing events - sessionID string - requestID atomic.Int64 - notificationChannel chan mcp.JSONRPCNotification - initialized atomic.Bool - loggingLevel atomic.Value - tools sync.Map // stores session-specific tools - clientInfo atomic.Value // stores session-specific client info -} - -// SSEContextFunc is a function that takes an existing context and the current -// request and returns a potentially modified context based on the request -// content. This can be used to inject context values from headers, for example. -type SSEContextFunc func(ctx context.Context, r *http.Request) context.Context - -// DynamicBasePathFunc allows the user to provide a function to generate the -// base path for a given request and sessionID. This is useful for cases where -// the base path is not known at the time of SSE server creation, such as when -// using a reverse proxy or when the base path is dynamically generated. The -// function should return the base path (e.g., "/mcp/tenant123"). -type DynamicBasePathFunc func(r *http.Request, sessionID string) string - -func (s *sseSession) SessionID() string { - return s.sessionID -} - -func (s *sseSession) NotificationChannel() chan<- mcp.JSONRPCNotification { - return s.notificationChannel -} - -func (s *sseSession) Initialize() { - // set default logging level - s.loggingLevel.Store(mcp.LoggingLevelError) - s.initialized.Store(true) -} - -func (s *sseSession) Initialized() bool { - return s.initialized.Load() -} - -func (s *sseSession) SetLogLevel(level mcp.LoggingLevel) { - s.loggingLevel.Store(level) -} - -func (s *sseSession) GetLogLevel() mcp.LoggingLevel { - level := s.loggingLevel.Load() - if level == nil { - return mcp.LoggingLevelError - } - return level.(mcp.LoggingLevel) -} - -func (s *sseSession) GetSessionTools() map[string]ServerTool { - tools := make(map[string]ServerTool) - s.tools.Range(func(key, value any) bool { - if tool, ok := value.(ServerTool); ok { - tools[key.(string)] = tool - } - return true - }) - return tools -} - -func (s *sseSession) SetSessionTools(tools map[string]ServerTool) { - // Clear existing tools - s.tools.Clear() - - // Set new tools - for name, tool := range tools { - s.tools.Store(name, tool) - } -} - -func (s *sseSession) GetClientInfo() mcp.Implementation { - if value := s.clientInfo.Load(); value != nil { - if clientInfo, ok := value.(mcp.Implementation); ok { - return clientInfo - } - } - return mcp.Implementation{} -} - -func (s *sseSession) SetClientInfo(clientInfo mcp.Implementation) { - s.clientInfo.Store(clientInfo) -} - -var ( - _ ClientSession = (*sseSession)(nil) - _ SessionWithTools = (*sseSession)(nil) - _ SessionWithLogging = (*sseSession)(nil) - _ SessionWithClientInfo = (*sseSession)(nil) -) - -// SSEServer implements a Server-Sent Events (SSE) based MCP server. -// It provides real-time communication capabilities over HTTP using the SSE protocol. -type SSEServer struct { - server *MCPServer - baseURL string - basePath string - appendQueryToMessageEndpoint bool - useFullURLForMessageEndpoint bool - messageEndpoint string - sseEndpoint string - sessions sync.Map - srv *http.Server - contextFunc SSEContextFunc - dynamicBasePathFunc DynamicBasePathFunc - - keepAlive bool - keepAliveInterval time.Duration - - mu sync.RWMutex -} - -// SSEOption defines a function type for configuring SSEServer -type SSEOption func(*SSEServer) - -// WithBaseURL sets the base URL for the SSE server -func WithBaseURL(baseURL string) SSEOption { - return func(s *SSEServer) { - if baseURL != "" { - u, err := url.Parse(baseURL) - if err != nil { - return - } - if u.Scheme != "http" && u.Scheme != "https" { - return - } - // Check if the host is empty or only contains a port - if u.Host == "" || strings.HasPrefix(u.Host, ":") { - return - } - if len(u.Query()) > 0 { - return - } - } - s.baseURL = strings.TrimSuffix(baseURL, "/") - } -} - -// WithStaticBasePath adds a new option for setting a static base path -func WithStaticBasePath(basePath string) SSEOption { - return func(s *SSEServer) { - s.basePath = normalizeURLPath(basePath) - } -} - -// WithBasePath adds a new option for setting a static base path. -// -// Deprecated: Use WithStaticBasePath instead. This will be removed in a future version. -// -//go:deprecated -func WithBasePath(basePath string) SSEOption { - return WithStaticBasePath(basePath) -} - -// WithDynamicBasePath accepts a function for generating the base path. This is -// useful for cases where the base path is not known at the time of SSE server -// creation, such as when using a reverse proxy or when the server is mounted -// at a dynamic path. -func WithDynamicBasePath(fn DynamicBasePathFunc) SSEOption { - return func(s *SSEServer) { - if fn != nil { - s.dynamicBasePathFunc = func(r *http.Request, sid string) string { - bp := fn(r, sid) - return normalizeURLPath(bp) - } - } - } -} - -// WithMessageEndpoint sets the message endpoint path -func WithMessageEndpoint(endpoint string) SSEOption { - return func(s *SSEServer) { - s.messageEndpoint = endpoint - } -} - -// WithAppendQueryToMessageEndpoint configures the SSE server to append the original request's -// query parameters to the message endpoint URL that is sent to clients during the SSE connection -// initialization. This is useful when you need to preserve query parameters from the initial -// SSE connection request and carry them over to subsequent message requests, maintaining -// context or authentication details across the communication channel. -func WithAppendQueryToMessageEndpoint() SSEOption { - return func(s *SSEServer) { - s.appendQueryToMessageEndpoint = true - } -} - -// WithUseFullURLForMessageEndpoint controls whether the SSE server returns a complete URL (including baseURL) -// or just the path portion for the message endpoint. Set to false when clients will concatenate -// the baseURL themselves to avoid malformed URLs like "http://localhost/mcphttp://localhost/mcp/message". -func WithUseFullURLForMessageEndpoint(useFullURLForMessageEndpoint bool) SSEOption { - return func(s *SSEServer) { - s.useFullURLForMessageEndpoint = useFullURLForMessageEndpoint - } -} - -// WithSSEEndpoint sets the SSE endpoint path -func WithSSEEndpoint(endpoint string) SSEOption { - return func(s *SSEServer) { - s.sseEndpoint = endpoint - } -} - -// WithHTTPServer sets the HTTP server instance. -// NOTE: When providing a custom HTTP server, you must handle routing yourself -// If routing is not set up, the server will start but won't handle any MCP requests. -func WithHTTPServer(srv *http.Server) SSEOption { - return func(s *SSEServer) { - s.srv = srv - } -} - -func WithKeepAliveInterval(keepAliveInterval time.Duration) SSEOption { - return func(s *SSEServer) { - s.keepAlive = true - s.keepAliveInterval = keepAliveInterval - } -} - -func WithKeepAlive(keepAlive bool) SSEOption { - return func(s *SSEServer) { - s.keepAlive = keepAlive - } -} - -// WithSSEContextFunc sets a function that will be called to customise the context -// to the server using the incoming request. -func WithSSEContextFunc(fn SSEContextFunc) SSEOption { - return func(s *SSEServer) { - s.contextFunc = fn - } -} - -// NewSSEServer creates a new SSE server instance with the given MCP server and options. -func NewSSEServer(server *MCPServer, opts ...SSEOption) *SSEServer { - s := &SSEServer{ - server: server, - sseEndpoint: "/sse", - messageEndpoint: "/message", - useFullURLForMessageEndpoint: true, - keepAlive: false, - keepAliveInterval: 10 * time.Second, - } - - // Apply all options - for _, opt := range opts { - opt(s) - } - - return s -} - -// NewTestServer creates a test server for testing purposes -func NewTestServer(server *MCPServer, opts ...SSEOption) *httptest.Server { - sseServer := NewSSEServer(server, opts...) - - testServer := httptest.NewServer(sseServer) - sseServer.baseURL = testServer.URL - return testServer -} - -// Start begins serving SSE connections on the specified address. -// It sets up HTTP handlers for SSE and message endpoints. -func (s *SSEServer) Start(addr string) error { - s.mu.Lock() - if s.srv == nil { - s.srv = &http.Server{ - Addr: addr, - Handler: s, - } - } else { - if s.srv.Addr == "" { - s.srv.Addr = addr - } else if s.srv.Addr != addr { - return fmt.Errorf("conflicting listen address: WithHTTPServer(%q) vs Start(%q)", s.srv.Addr, addr) - } - } - srv := s.srv - s.mu.Unlock() - - return srv.ListenAndServe() -} - -// Shutdown gracefully stops the SSE server, closing all active sessions -// and shutting down the HTTP server. -func (s *SSEServer) Shutdown(ctx context.Context) error { - s.mu.RLock() - srv := s.srv - s.mu.RUnlock() - - if srv != nil { - s.sessions.Range(func(key, value any) bool { - if session, ok := value.(*sseSession); ok { - close(session.done) - } - s.sessions.Delete(key) - return true - }) - - return srv.Shutdown(ctx) - } - return nil -} - -// handleSSE handles incoming SSE connection requests. -// It sets up appropriate headers and creates a new session for the client. -func (s *SSEServer) handleSSE(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { - http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) - return - } - - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Cache-Control", "no-cache") - w.Header().Set("Connection", "keep-alive") - w.Header().Set("Access-Control-Allow-Origin", "*") - - flusher, ok := w.(http.Flusher) - if !ok { - http.Error(w, "Streaming unsupported", http.StatusInternalServerError) - return - } - - sessionID := uuid.New().String() - session := &sseSession{ - done: make(chan struct{}), - eventQueue: make(chan string, 100), // Buffer for events - sessionID: sessionID, - notificationChannel: make(chan mcp.JSONRPCNotification, 100), - } - - s.sessions.Store(sessionID, session) - defer s.sessions.Delete(sessionID) - - if err := s.server.RegisterSession(r.Context(), session); err != nil { - http.Error( - w, - fmt.Sprintf("Session registration failed: %v", err), - http.StatusInternalServerError, - ) - return - } - defer s.server.UnregisterSession(r.Context(), sessionID) - - // Start notification handler for this session - go func() { - for { - select { - case notification := <-session.notificationChannel: - eventData, err := json.Marshal(notification) - if err == nil { - select { - case session.eventQueue <- fmt.Sprintf("event: message\ndata: %s\n\n", eventData): - // Event queued successfully - case <-session.done: - return - } - } - case <-session.done: - return - case <-r.Context().Done(): - return - } - } - }() - - // Start keep alive : ping - if s.keepAlive { - go func() { - ticker := time.NewTicker(s.keepAliveInterval) - defer ticker.Stop() - for { - select { - case <-ticker.C: - message := mcp.JSONRPCRequest{ - JSONRPC: "2.0", - ID: mcp.NewRequestId(session.requestID.Add(1)), - Request: mcp.Request{ - Method: "ping", - }, - } - messageBytes, _ := json.Marshal(message) - pingMsg := fmt.Sprintf("event: message\ndata:%s\n\n", messageBytes) - select { - case session.eventQueue <- pingMsg: - // Message sent successfully - case <-session.done: - return - } - case <-session.done: - return - case <-r.Context().Done(): - return - } - } - }() - } - - // Send the initial endpoint event - endpoint := s.GetMessageEndpointForClient(r, sessionID) - if s.appendQueryToMessageEndpoint && len(r.URL.RawQuery) > 0 { - endpoint += "&" + r.URL.RawQuery - } - fmt.Fprintf(w, "event: endpoint\ndata: %s\r\n\r\n", endpoint) - flusher.Flush() - - // Main event loop - this runs in the HTTP handler goroutine - for { - select { - case event := <-session.eventQueue: - // Write the event to the response - fmt.Fprint(w, event) - flusher.Flush() - case <-r.Context().Done(): - close(session.done) - return - case <-session.done: - return - } - } -} - -// GetMessageEndpointForClient returns the appropriate message endpoint URL with session ID -// for the given request. This is the canonical way to compute the message endpoint for a client. -// It handles both dynamic and static path modes, and honors the WithUseFullURLForMessageEndpoint flag. -func (s *SSEServer) GetMessageEndpointForClient(r *http.Request, sessionID string) string { - basePath := s.basePath - if s.dynamicBasePathFunc != nil { - basePath = s.dynamicBasePathFunc(r, sessionID) - } - - endpointPath := normalizeURLPath(basePath, s.messageEndpoint) - if s.useFullURLForMessageEndpoint && s.baseURL != "" { - endpointPath = s.baseURL + endpointPath - } - - return fmt.Sprintf("%s?sessionId=%s", endpointPath, sessionID) -} - -// handleMessage processes incoming JSON-RPC messages from clients and sends responses -// back through the SSE connection and 202 code to HTTP response. -func (s *SSEServer) handleMessage(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - s.writeJSONRPCError(w, nil, mcp.INVALID_REQUEST, "Method not allowed") - return - } - - sessionID := r.URL.Query().Get("sessionId") - if sessionID == "" { - s.writeJSONRPCError(w, nil, mcp.INVALID_PARAMS, "Missing sessionId") - return - } - sessionI, ok := s.sessions.Load(sessionID) - if !ok { - s.writeJSONRPCError(w, nil, mcp.INVALID_PARAMS, "Invalid session ID") - return - } - session := sessionI.(*sseSession) - - // Set the client context before handling the message - ctx := s.server.WithContext(r.Context(), session) - if s.contextFunc != nil { - ctx = s.contextFunc(ctx, r) - } - - // Parse message as raw JSON - var rawMessage json.RawMessage - if err := json.NewDecoder(r.Body).Decode(&rawMessage); err != nil { - s.writeJSONRPCError(w, nil, mcp.PARSE_ERROR, "Parse error") - return - } - - // Create a context that preserves all values from parent ctx but won't be canceled when the parent is canceled. - // this is required because the http ctx will be canceled when the client disconnects - detachedCtx := context.WithoutCancel(ctx) - - // quick return request, send 202 Accepted with no body, then deal the message and sent response via SSE - w.WriteHeader(http.StatusAccepted) - - // Create a new context for handling the message that will be canceled when the message handling is done - messageCtx, cancel := context.WithCancel(detachedCtx) - - go func(ctx context.Context) { - defer cancel() - // Use the context that will be canceled when session is done - // Process message through MCPServer - response := s.server.HandleMessage(ctx, rawMessage) - // Only send response if there is one (not for notifications) - if response != nil { - var message string - if eventData, err := json.Marshal(response); err != nil { - // If there is an error marshalling the response, send a generic error response - log.Printf("failed to marshal response: %v", err) - message = "event: message\ndata: {\"error\": \"internal error\",\"jsonrpc\": \"2.0\", \"id\": null}\n\n" - } else { - message = fmt.Sprintf("event: message\ndata: %s\n\n", eventData) - } - - // Queue the event for sending via SSE - select { - case session.eventQueue <- message: - // Event queued successfully - case <-session.done: - // Session is closed, don't try to queue - default: - // Queue is full, log this situation - log.Printf("Event queue full for session %s", sessionID) - } - } - }(messageCtx) -} - -// writeJSONRPCError writes a JSON-RPC error response with the given error details. -func (s *SSEServer) writeJSONRPCError( - w http.ResponseWriter, - id any, - code int, - message string, -) { - response := createErrorResponse(id, code, message) - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusBadRequest) - if err := json.NewEncoder(w).Encode(response); err != nil { - http.Error( - w, - fmt.Sprintf("Failed to encode response: %v", err), - http.StatusInternalServerError, - ) - return - } -} - -// SendEventToSession sends an event to a specific SSE session identified by sessionID. -// Returns an error if the session is not found or closed. -func (s *SSEServer) SendEventToSession( - sessionID string, - event any, -) error { - sessionI, ok := s.sessions.Load(sessionID) - if !ok { - return fmt.Errorf("session not found: %s", sessionID) - } - session := sessionI.(*sseSession) - - eventData, err := json.Marshal(event) - if err != nil { - return err - } - - // Queue the event for sending via SSE - select { - case session.eventQueue <- fmt.Sprintf("event: message\ndata: %s\n\n", eventData): - return nil - case <-session.done: - return fmt.Errorf("session closed") - default: - return fmt.Errorf("event queue full") - } -} - -func (s *SSEServer) GetUrlPath(input string) (string, error) { - parse, err := url.Parse(input) - if err != nil { - return "", fmt.Errorf("failed to parse URL %s: %w", input, err) - } - return parse.Path, nil -} - -func (s *SSEServer) CompleteSseEndpoint() (string, error) { - if s.dynamicBasePathFunc != nil { - return "", &ErrDynamicPathConfig{Method: "CompleteSseEndpoint"} - } - - path := normalizeURLPath(s.basePath, s.sseEndpoint) - return s.baseURL + path, nil -} - -func (s *SSEServer) CompleteSsePath() string { - path, err := s.CompleteSseEndpoint() - if err != nil { - return normalizeURLPath(s.basePath, s.sseEndpoint) - } - urlPath, err := s.GetUrlPath(path) - if err != nil { - return normalizeURLPath(s.basePath, s.sseEndpoint) - } - return urlPath -} - -func (s *SSEServer) CompleteMessageEndpoint() (string, error) { - if s.dynamicBasePathFunc != nil { - return "", &ErrDynamicPathConfig{Method: "CompleteMessageEndpoint"} - } - path := normalizeURLPath(s.basePath, s.messageEndpoint) - return s.baseURL + path, nil -} - -func (s *SSEServer) CompleteMessagePath() string { - path, err := s.CompleteMessageEndpoint() - if err != nil { - return normalizeURLPath(s.basePath, s.messageEndpoint) - } - urlPath, err := s.GetUrlPath(path) - if err != nil { - return normalizeURLPath(s.basePath, s.messageEndpoint) - } - return urlPath -} - -// SSEHandler returns an http.Handler for the SSE endpoint. -// -// This method allows you to mount the SSE handler at any arbitrary path -// using your own router (e.g. net/http, gorilla/mux, chi, etc.). It is -// intended for advanced scenarios where you want to control the routing or -// support dynamic segments. -// -// IMPORTANT: When using this handler in advanced/dynamic mounting scenarios, -// you must use the WithDynamicBasePath option to ensure the correct base path -// is communicated to clients. -// -// Example usage: -// -// // Advanced/dynamic: -// sseServer := NewSSEServer(mcpServer, -// WithDynamicBasePath(func(r *http.Request, sessionID string) string { -// tenant := r.PathValue("tenant") -// return "/mcp/" + tenant -// }), -// WithBaseURL("http://localhost:8080") -// ) -// mux.Handle("/mcp/{tenant}/sse", sseServer.SSEHandler()) -// mux.Handle("/mcp/{tenant}/message", sseServer.MessageHandler()) -// -// For non-dynamic cases, use ServeHTTP method instead. -func (s *SSEServer) SSEHandler() http.Handler { - return http.HandlerFunc(s.handleSSE) -} - -// MessageHandler returns an http.Handler for the message endpoint. -// -// This method allows you to mount the message handler at any arbitrary path -// using your own router (e.g. net/http, gorilla/mux, chi, etc.). It is -// intended for advanced scenarios where you want to control the routing or -// support dynamic segments. -// -// IMPORTANT: When using this handler in advanced/dynamic mounting scenarios, -// you must use the WithDynamicBasePath option to ensure the correct base path -// is communicated to clients. -// -// Example usage: -// -// // Advanced/dynamic: -// sseServer := NewSSEServer(mcpServer, -// WithDynamicBasePath(func(r *http.Request, sessionID string) string { -// tenant := r.PathValue("tenant") -// return "/mcp/" + tenant -// }), -// WithBaseURL("http://localhost:8080") -// ) -// mux.Handle("/mcp/{tenant}/sse", sseServer.SSEHandler()) -// mux.Handle("/mcp/{tenant}/message", sseServer.MessageHandler()) -// -// For non-dynamic cases, use ServeHTTP method instead. -func (s *SSEServer) MessageHandler() http.Handler { - return http.HandlerFunc(s.handleMessage) -} - -// ServeHTTP implements the http.Handler interface. -func (s *SSEServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if s.dynamicBasePathFunc != nil { - http.Error( - w, - (&ErrDynamicPathConfig{Method: "ServeHTTP"}).Error(), - http.StatusInternalServerError, - ) - return - } - path := r.URL.Path - // Use exact path matching rather than Contains - ssePath := s.CompleteSsePath() - if ssePath != "" && path == ssePath { - s.handleSSE(w, r) - return - } - messagePath := s.CompleteMessagePath() - if messagePath != "" && path == messagePath { - s.handleMessage(w, r) - return - } - - http.NotFound(w, r) -} - -// normalizeURLPath joins path elements like path.Join but ensures the -// result always starts with a leading slash and never ends with a slash -func normalizeURLPath(elem ...string) string { - joined := path.Join(elem...) - - // Ensure leading slash - if !strings.HasPrefix(joined, "/") { - joined = "/" + joined - } - - // Remove trailing slash if not just "/" - if len(joined) > 1 && strings.HasSuffix(joined, "/") { - joined = joined[:len(joined)-1] - } - - return joined -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/stdio.go b/vendor/github.com/mark3labs/mcp-go/server/stdio.go deleted file mode 100644 index 33ac9bb885..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/stdio.go +++ /dev/null @@ -1,482 +0,0 @@ -package server - -import ( - "bufio" - "context" - "encoding/json" - "fmt" - "io" - "log" - "os" - "os/signal" - "sync" - "sync/atomic" - "syscall" - - "github.com/mark3labs/mcp-go/mcp" -) - -// StdioContextFunc is a function that takes an existing context and returns -// a potentially modified context. -// This can be used to inject context values from environment variables, -// for example. -type StdioContextFunc func(ctx context.Context) context.Context - -// StdioServer wraps a MCPServer and handles stdio communication. -// It provides a simple way to create command-line MCP servers that -// communicate via standard input/output streams using JSON-RPC messages. -type StdioServer struct { - server *MCPServer - errLogger *log.Logger - contextFunc StdioContextFunc -} - -// StdioOption defines a function type for configuring StdioServer -type StdioOption func(*StdioServer) - -// WithErrorLogger sets the error logger for the server -func WithErrorLogger(logger *log.Logger) StdioOption { - return func(s *StdioServer) { - s.errLogger = logger - } -} - -// WithStdioContextFunc sets a function that will be called to customise the context -// to the server. Note that the stdio server uses the same context for all requests, -// so this function will only be called once per server instance. -func WithStdioContextFunc(fn StdioContextFunc) StdioOption { - return func(s *StdioServer) { - s.contextFunc = fn - } -} - -// stdioSession is a static client session, since stdio has only one client. -type stdioSession struct { - notifications chan mcp.JSONRPCNotification - initialized atomic.Bool - loggingLevel atomic.Value - clientInfo atomic.Value // stores session-specific client info - writer io.Writer // for sending requests to client - requestID atomic.Int64 // for generating unique request IDs - mu sync.RWMutex // protects writer - pendingRequests map[int64]chan *samplingResponse // for tracking pending sampling requests - pendingMu sync.RWMutex // protects pendingRequests -} - -// samplingResponse represents a response to a sampling request -type samplingResponse struct { - result *mcp.CreateMessageResult - err error -} - -func (s *stdioSession) SessionID() string { - return "stdio" -} - -func (s *stdioSession) NotificationChannel() chan<- mcp.JSONRPCNotification { - return s.notifications -} - -func (s *stdioSession) Initialize() { - // set default logging level - s.loggingLevel.Store(mcp.LoggingLevelError) - s.initialized.Store(true) -} - -func (s *stdioSession) Initialized() bool { - return s.initialized.Load() -} - -func (s *stdioSession) GetClientInfo() mcp.Implementation { - if value := s.clientInfo.Load(); value != nil { - if clientInfo, ok := value.(mcp.Implementation); ok { - return clientInfo - } - } - return mcp.Implementation{} -} - -func (s *stdioSession) SetClientInfo(clientInfo mcp.Implementation) { - s.clientInfo.Store(clientInfo) -} - -func (s *stdioSession) SetLogLevel(level mcp.LoggingLevel) { - s.loggingLevel.Store(level) -} - -func (s *stdioSession) GetLogLevel() mcp.LoggingLevel { - level := s.loggingLevel.Load() - if level == nil { - return mcp.LoggingLevelError - } - return level.(mcp.LoggingLevel) -} - -// RequestSampling sends a sampling request to the client and waits for the response. -func (s *stdioSession) RequestSampling(ctx context.Context, request mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) { - s.mu.RLock() - writer := s.writer - s.mu.RUnlock() - - if writer == nil { - return nil, fmt.Errorf("no writer available for sending requests") - } - - // Generate a unique request ID - id := s.requestID.Add(1) - - // Create a response channel for this request - responseChan := make(chan *samplingResponse, 1) - s.pendingMu.Lock() - s.pendingRequests[id] = responseChan - s.pendingMu.Unlock() - - // Cleanup function to remove the pending request - cleanup := func() { - s.pendingMu.Lock() - delete(s.pendingRequests, id) - s.pendingMu.Unlock() - } - defer cleanup() - - // Create the JSON-RPC request - jsonRPCRequest := struct { - JSONRPC string `json:"jsonrpc"` - ID int64 `json:"id"` - Method string `json:"method"` - Params mcp.CreateMessageParams `json:"params"` - }{ - JSONRPC: mcp.JSONRPC_VERSION, - ID: id, - Method: string(mcp.MethodSamplingCreateMessage), - Params: request.CreateMessageParams, - } - - // Marshal and send the request - requestBytes, err := json.Marshal(jsonRPCRequest) - if err != nil { - return nil, fmt.Errorf("failed to marshal sampling request: %w", err) - } - requestBytes = append(requestBytes, '\n') - - if _, err := writer.Write(requestBytes); err != nil { - return nil, fmt.Errorf("failed to write sampling request: %w", err) - } - - // Wait for the response or context cancellation - select { - case <-ctx.Done(): - return nil, ctx.Err() - case response := <-responseChan: - if response.err != nil { - return nil, response.err - } - return response.result, nil - } -} - -// SetWriter sets the writer for sending requests to the client. -func (s *stdioSession) SetWriter(writer io.Writer) { - s.mu.Lock() - defer s.mu.Unlock() - s.writer = writer -} - -var ( - _ ClientSession = (*stdioSession)(nil) - _ SessionWithLogging = (*stdioSession)(nil) - _ SessionWithClientInfo = (*stdioSession)(nil) - _ SessionWithSampling = (*stdioSession)(nil) -) - -var stdioSessionInstance = stdioSession{ - notifications: make(chan mcp.JSONRPCNotification, 100), - pendingRequests: make(map[int64]chan *samplingResponse), -} - -// NewStdioServer creates a new stdio server wrapper around an MCPServer. -// It initializes the server with a default error logger that discards all output. -func NewStdioServer(server *MCPServer) *StdioServer { - return &StdioServer{ - server: server, - errLogger: log.New( - os.Stderr, - "", - log.LstdFlags, - ), // Default to discarding logs - } -} - -// SetErrorLogger configures where error messages from the StdioServer are logged. -// The provided logger will receive all error messages generated during server operation. -func (s *StdioServer) SetErrorLogger(logger *log.Logger) { - s.errLogger = logger -} - -// SetContextFunc sets a function that will be called to customise the context -// to the server. Note that the stdio server uses the same context for all requests, -// so this function will only be called once per server instance. -func (s *StdioServer) SetContextFunc(fn StdioContextFunc) { - s.contextFunc = fn -} - -// handleNotifications continuously processes notifications from the session's notification channel -// and writes them to the provided output. It runs until the context is cancelled. -// Any errors encountered while writing notifications are logged but do not stop the handler. -func (s *StdioServer) handleNotifications(ctx context.Context, stdout io.Writer) { - for { - select { - case notification := <-stdioSessionInstance.notifications: - if err := s.writeResponse(notification, stdout); err != nil { - s.errLogger.Printf("Error writing notification: %v", err) - } - case <-ctx.Done(): - return - } - } -} - -// processInputStream continuously reads and processes messages from the input stream. -// It handles EOF gracefully as a normal termination condition. -// The function returns when either: -// - The context is cancelled (returns context.Err()) -// - EOF is encountered (returns nil) -// - An error occurs while reading or processing messages (returns the error) -func (s *StdioServer) processInputStream(ctx context.Context, reader *bufio.Reader, stdout io.Writer) error { - for { - if err := ctx.Err(); err != nil { - return err - } - - line, err := s.readNextLine(ctx, reader) - if err != nil { - if err == io.EOF { - return nil - } - s.errLogger.Printf("Error reading input: %v", err) - return err - } - - if err := s.processMessage(ctx, line, stdout); err != nil { - if err == io.EOF { - return nil - } - s.errLogger.Printf("Error handling message: %v", err) - return err - } - } -} - -// readNextLine reads a single line from the input reader in a context-aware manner. -// It uses channels to make the read operation cancellable via context. -// Returns the read line and any error encountered. If the context is cancelled, -// returns an empty string and the context's error. EOF is returned when the input -// stream is closed. -func (s *StdioServer) readNextLine(ctx context.Context, reader *bufio.Reader) (string, error) { - type result struct { - line string - err error - } - - resultCh := make(chan result, 1) - - go func() { - line, err := reader.ReadString('\n') - resultCh <- result{line: line, err: err} - }() - - select { - case <-ctx.Done(): - return "", nil - case res := <-resultCh: - return res.line, res.err - } -} - -// Listen starts listening for JSON-RPC messages on the provided input and writes responses to the provided output. -// It runs until the context is cancelled or an error occurs. -// Returns an error if there are issues with reading input or writing output. -func (s *StdioServer) Listen( - ctx context.Context, - stdin io.Reader, - stdout io.Writer, -) error { - // Set a static client context since stdio only has one client - if err := s.server.RegisterSession(ctx, &stdioSessionInstance); err != nil { - return fmt.Errorf("register session: %w", err) - } - defer s.server.UnregisterSession(ctx, stdioSessionInstance.SessionID()) - ctx = s.server.WithContext(ctx, &stdioSessionInstance) - - // Set the writer for sending requests to the client - stdioSessionInstance.SetWriter(stdout) - - // Add in any custom context. - if s.contextFunc != nil { - ctx = s.contextFunc(ctx) - } - - reader := bufio.NewReader(stdin) - - // Start notification handler - go s.handleNotifications(ctx, stdout) - return s.processInputStream(ctx, reader, stdout) -} - -// processMessage handles a single JSON-RPC message and writes the response. -// It parses the message, processes it through the wrapped MCPServer, and writes any response. -// Returns an error if there are issues with message processing or response writing. -func (s *StdioServer) processMessage( - ctx context.Context, - line string, - writer io.Writer, -) error { - // If line is empty, likely due to ctx cancellation - if len(line) == 0 { - return nil - } - - // Parse the message as raw JSON - var rawMessage json.RawMessage - if err := json.Unmarshal([]byte(line), &rawMessage); err != nil { - response := createErrorResponse(nil, mcp.PARSE_ERROR, "Parse error") - return s.writeResponse(response, writer) - } - - // Check if this is a response to a sampling request - if s.handleSamplingResponse(rawMessage) { - return nil - } - - // Check if this is a tool call that might need sampling (and thus should be processed concurrently) - var baseMessage struct { - Method string `json:"method"` - } - if json.Unmarshal(rawMessage, &baseMessage) == nil && baseMessage.Method == "tools/call" { - // Process tool calls concurrently to avoid blocking on sampling requests - go func() { - response := s.server.HandleMessage(ctx, rawMessage) - if response != nil { - if err := s.writeResponse(response, writer); err != nil { - s.errLogger.Printf("Error writing tool response: %v", err) - } - } - }() - return nil - } - - // Handle other messages synchronously - response := s.server.HandleMessage(ctx, rawMessage) - - // Only write response if there is one (not for notifications) - if response != nil { - if err := s.writeResponse(response, writer); err != nil { - return fmt.Errorf("failed to write response: %w", err) - } - } - - return nil -} - -// handleSamplingResponse checks if the message is a response to a sampling request -// and routes it to the appropriate pending request channel. -func (s *StdioServer) handleSamplingResponse(rawMessage json.RawMessage) bool { - return stdioSessionInstance.handleSamplingResponse(rawMessage) -} - -// handleSamplingResponse handles incoming sampling responses for this session -func (s *stdioSession) handleSamplingResponse(rawMessage json.RawMessage) bool { - // Try to parse as a JSON-RPC response - var response struct { - JSONRPC string `json:"jsonrpc"` - ID json.Number `json:"id"` - Result json.RawMessage `json:"result,omitempty"` - Error *struct { - Code int `json:"code"` - Message string `json:"message"` - } `json:"error,omitempty"` - } - - if err := json.Unmarshal(rawMessage, &response); err != nil { - return false - } - // Parse the ID as int64 - idInt64, err := response.ID.Int64() - if err != nil || (response.Result == nil && response.Error == nil) { - return false - } - - // Look for a pending request with this ID - s.pendingMu.RLock() - responseChan, exists := s.pendingRequests[idInt64] - s.pendingMu.RUnlock() - - if !exists { - return false - } // Parse and send the response - samplingResp := &samplingResponse{} - - if response.Error != nil { - samplingResp.err = fmt.Errorf("sampling request failed: %s", response.Error.Message) - } else { - var result mcp.CreateMessageResult - if err := json.Unmarshal(response.Result, &result); err != nil { - samplingResp.err = fmt.Errorf("failed to unmarshal sampling response: %w", err) - } else { - samplingResp.result = &result - } - } - - // Send the response (non-blocking) - select { - case responseChan <- samplingResp: - default: - // Channel is full or closed, ignore - } - - return true -} - -// writeResponse marshals and writes a JSON-RPC response message followed by a newline. -// Returns an error if marshaling or writing fails. -func (s *StdioServer) writeResponse( - response mcp.JSONRPCMessage, - writer io.Writer, -) error { - responseBytes, err := json.Marshal(response) - if err != nil { - return err - } - - // Write response followed by newline - if _, err := fmt.Fprintf(writer, "%s\n", responseBytes); err != nil { - return err - } - - return nil -} - -// ServeStdio is a convenience function that creates and starts a StdioServer with os.Stdin and os.Stdout. -// It sets up signal handling for graceful shutdown on SIGTERM and SIGINT. -// Returns an error if the server encounters any issues during operation. -func ServeStdio(server *MCPServer, opts ...StdioOption) error { - s := NewStdioServer(server) - - for _, opt := range opts { - opt(s) - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // Set up signal handling - sigChan := make(chan os.Signal, 1) - signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT) - - go func() { - <-sigChan - cancel() - }() - - return s.Listen(ctx, os.Stdin, os.Stdout) -} diff --git a/vendor/github.com/mark3labs/mcp-go/server/streamable_http.go b/vendor/github.com/mark3labs/mcp-go/server/streamable_http.go deleted file mode 100644 index 1312c9753a..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/server/streamable_http.go +++ /dev/null @@ -1,655 +0,0 @@ -package server - -import ( - "context" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httptest" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/google/uuid" - "github.com/mark3labs/mcp-go/mcp" - "github.com/mark3labs/mcp-go/util" -) - -// StreamableHTTPOption defines a function type for configuring StreamableHTTPServer -type StreamableHTTPOption func(*StreamableHTTPServer) - -// WithEndpointPath sets the endpoint path for the server. -// The default is "/mcp". -// It's only works for `Start` method. When used as a http.Handler, it has no effect. -func WithEndpointPath(endpointPath string) StreamableHTTPOption { - return func(s *StreamableHTTPServer) { - // Normalize the endpoint path to ensure it starts with a slash and doesn't end with one - normalizedPath := "/" + strings.Trim(endpointPath, "/") - s.endpointPath = normalizedPath - } -} - -// WithStateLess sets the server to stateless mode. -// If true, the server will manage no session information. Every request will be treated -// as a new session. No session id returned to the client. -// The default is false. -// -// Notice: This is a convenience method. It's identical to set WithSessionIdManager option -// to StatelessSessionIdManager. -func WithStateLess(stateLess bool) StreamableHTTPOption { - return func(s *StreamableHTTPServer) { - if stateLess { - s.sessionIdManager = &StatelessSessionIdManager{} - } - } -} - -// WithSessionIdManager sets a custom session id generator for the server. -// By default, the server will use SimpleStatefulSessionIdGenerator, which generates -// session ids with uuid, and it's insecure. -// Notice: it will override the WithStateLess option. -func WithSessionIdManager(manager SessionIdManager) StreamableHTTPOption { - return func(s *StreamableHTTPServer) { - s.sessionIdManager = manager - } -} - -// WithHeartbeatInterval sets the heartbeat interval. Positive interval means the -// server will send a heartbeat to the client through the GET connection, to keep -// the connection alive from being closed by the network infrastructure (e.g. -// gateways). If the client does not establish a GET connection, it has no -// effect. The default is not to send heartbeats. -func WithHeartbeatInterval(interval time.Duration) StreamableHTTPOption { - return func(s *StreamableHTTPServer) { - s.listenHeartbeatInterval = interval - } -} - -// WithHTTPContextFunc sets a function that will be called to customise the context -// to the server using the incoming request. -// This can be used to inject context values from headers, for example. -func WithHTTPContextFunc(fn HTTPContextFunc) StreamableHTTPOption { - return func(s *StreamableHTTPServer) { - s.contextFunc = fn - } -} - -// WithStreamableHTTPServer sets the HTTP server instance for StreamableHTTPServer. -// NOTE: When providing a custom HTTP server, you must handle routing yourself -// If routing is not set up, the server will start but won't handle any MCP requests. -func WithStreamableHTTPServer(srv *http.Server) StreamableHTTPOption { - return func(s *StreamableHTTPServer) { - s.httpServer = srv - } -} - -// WithLogger sets the logger for the server -func WithLogger(logger util.Logger) StreamableHTTPOption { - return func(s *StreamableHTTPServer) { - s.logger = logger - } -} - -// StreamableHTTPServer implements a Streamable-http based MCP server. -// It communicates with clients over HTTP protocol, supporting both direct HTTP responses, and SSE streams. -// https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http -// -// Usage: -// -// server := NewStreamableHTTPServer(mcpServer) -// server.Start(":8080") // The final url for client is http://xxxx:8080/mcp by default -// -// or the server itself can be used as a http.Handler, which is convenient to -// integrate with existing http servers, or advanced usage: -// -// handler := NewStreamableHTTPServer(mcpServer) -// http.Handle("/streamable-http", handler) -// http.ListenAndServe(":8080", nil) -// -// Notice: -// Except for the GET handlers(listening), the POST handlers(request/notification) will -// not trigger the session registration. So the methods like `SendNotificationToSpecificClient` -// or `hooks.onRegisterSession` will not be triggered for POST messages. -// -// The current implementation does not support the following features from the specification: -// - Batching of requests/notifications/responses in arrays. -// - Stream Resumability -type StreamableHTTPServer struct { - server *MCPServer - sessionTools *sessionToolsStore - sessionRequestIDs sync.Map // sessionId --> last requestID(*atomic.Int64) - - httpServer *http.Server - mu sync.RWMutex - - endpointPath string - contextFunc HTTPContextFunc - sessionIdManager SessionIdManager - listenHeartbeatInterval time.Duration - logger util.Logger -} - -// NewStreamableHTTPServer creates a new streamable-http server instance -func NewStreamableHTTPServer(server *MCPServer, opts ...StreamableHTTPOption) *StreamableHTTPServer { - s := &StreamableHTTPServer{ - server: server, - sessionTools: newSessionToolsStore(), - endpointPath: "/mcp", - sessionIdManager: &InsecureStatefulSessionIdManager{}, - logger: util.DefaultLogger(), - } - - // Apply all options - for _, opt := range opts { - opt(s) - } - return s -} - -// ServeHTTP implements the http.Handler interface. -func (s *StreamableHTTPServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodPost: - s.handlePost(w, r) - case http.MethodGet: - s.handleGet(w, r) - case http.MethodDelete: - s.handleDelete(w, r) - default: - http.NotFound(w, r) - } -} - -// Start begins serving the http server on the specified address and path -// (endpointPath). like: -// -// s.Start(":8080") -func (s *StreamableHTTPServer) Start(addr string) error { - s.mu.Lock() - if s.httpServer == nil { - mux := http.NewServeMux() - mux.Handle(s.endpointPath, s) - s.httpServer = &http.Server{ - Addr: addr, - Handler: mux, - } - } else { - if s.httpServer.Addr == "" { - s.httpServer.Addr = addr - } else if s.httpServer.Addr != addr { - return fmt.Errorf("conflicting listen address: WithStreamableHTTPServer(%q) vs Start(%q)", s.httpServer.Addr, addr) - } - } - srv := s.httpServer - s.mu.Unlock() - - return srv.ListenAndServe() -} - -// Shutdown gracefully stops the server, closing all active sessions -// and shutting down the HTTP server. -func (s *StreamableHTTPServer) Shutdown(ctx context.Context) error { - - // shutdown the server if needed (may use as a http.Handler) - s.mu.RLock() - srv := s.httpServer - s.mu.RUnlock() - if srv != nil { - return srv.Shutdown(ctx) - } - return nil -} - -// --- internal methods --- - -const ( - headerKeySessionID = "Mcp-Session-Id" -) - -func (s *StreamableHTTPServer) handlePost(w http.ResponseWriter, r *http.Request) { - // post request carry request/notification message - - // Check content type - contentType := r.Header.Get("Content-Type") - if contentType != "application/json" { - http.Error(w, "Invalid content type: must be 'application/json'", http.StatusBadRequest) - return - } - - // Check the request body is valid json, meanwhile, get the request Method - rawData, err := io.ReadAll(r.Body) - if err != nil { - s.writeJSONRPCError(w, nil, mcp.PARSE_ERROR, fmt.Sprintf("read request body error: %v", err)) - return - } - var baseMessage struct { - Method mcp.MCPMethod `json:"method"` - } - if err := json.Unmarshal(rawData, &baseMessage); err != nil { - s.writeJSONRPCError(w, nil, mcp.PARSE_ERROR, "request body is not valid json") - return - } - isInitializeRequest := baseMessage.Method == mcp.MethodInitialize - - // Prepare the session for the mcp server - // The session is ephemeral. Its life is the same as the request. It's only created - // for interaction with the mcp server. - var sessionID string - if isInitializeRequest { - // generate a new one for initialize request - sessionID = s.sessionIdManager.Generate() - } else { - // Get session ID from header. - // Stateful servers need the client to carry the session ID. - sessionID = r.Header.Get(headerKeySessionID) - isTerminated, err := s.sessionIdManager.Validate(sessionID) - if err != nil { - http.Error(w, "Invalid session ID", http.StatusBadRequest) - return - } - if isTerminated { - http.Error(w, "Session terminated", http.StatusNotFound) - return - } - } - - session := newStreamableHttpSession(sessionID, s.sessionTools) - - // Set the client context before handling the message - ctx := s.server.WithContext(r.Context(), session) - if s.contextFunc != nil { - ctx = s.contextFunc(ctx, r) - } - - // handle potential notifications - mu := sync.Mutex{} - upgradedHeader := false - done := make(chan struct{}) - - go func() { - for { - select { - case nt := <-session.notificationChannel: - func() { - mu.Lock() - defer mu.Unlock() - // if the done chan is closed, as the request is terminated, just return - select { - case <-done: - return - default: - } - defer func() { - flusher, ok := w.(http.Flusher) - if ok { - flusher.Flush() - } - }() - - // if there's notifications, upgradedHeader to SSE response - if !upgradedHeader { - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Connection", "keep-alive") - w.Header().Set("Cache-Control", "no-cache") - w.WriteHeader(http.StatusAccepted) - upgradedHeader = true - } - err := writeSSEEvent(w, nt) - if err != nil { - s.logger.Errorf("Failed to write SSE event: %v", err) - return - } - }() - case <-done: - return - case <-ctx.Done(): - return - } - } - }() - - // Process message through MCPServer - response := s.server.HandleMessage(ctx, rawData) - if response == nil { - // For notifications, just send 202 Accepted with no body - w.WriteHeader(http.StatusAccepted) - return - } - - // Write response - mu.Lock() - defer mu.Unlock() - // close the done chan before unlock - defer close(done) - if ctx.Err() != nil { - return - } - // If client-server communication already upgraded to SSE stream - if session.upgradeToSSE.Load() { - if !upgradedHeader { - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Connection", "keep-alive") - w.Header().Set("Cache-Control", "no-cache") - w.WriteHeader(http.StatusAccepted) - upgradedHeader = true - } - if err := writeSSEEvent(w, response); err != nil { - s.logger.Errorf("Failed to write final SSE response event: %v", err) - } - } else { - w.Header().Set("Content-Type", "application/json") - if isInitializeRequest && sessionID != "" { - // send the session ID back to the client - w.Header().Set(headerKeySessionID, sessionID) - } - w.WriteHeader(http.StatusOK) - err := json.NewEncoder(w).Encode(response) - if err != nil { - s.logger.Errorf("Failed to write response: %v", err) - } - } -} - -func (s *StreamableHTTPServer) handleGet(w http.ResponseWriter, r *http.Request) { - // get request is for listening to notifications - // https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#listening-for-messages-from-the-server - - sessionID := r.Header.Get(headerKeySessionID) - // the specification didn't say we should validate the session id - - if sessionID == "" { - // It's a stateless server, - // but the MCP server requires a unique ID for registering, so we use a random one - sessionID = uuid.New().String() - } - - session := newStreamableHttpSession(sessionID, s.sessionTools) - if err := s.server.RegisterSession(r.Context(), session); err != nil { - http.Error(w, fmt.Sprintf("Session registration failed: %v", err), http.StatusBadRequest) - return - } - defer s.server.UnregisterSession(r.Context(), sessionID) - - // Set the client context before handling the message - w.Header().Set("Content-Type", "text/event-stream") - w.Header().Set("Cache-Control", "no-cache") - w.Header().Set("Connection", "keep-alive") - w.WriteHeader(http.StatusOK) - - flusher, ok := w.(http.Flusher) - if !ok { - http.Error(w, "Streaming unsupported", http.StatusInternalServerError) - return - } - flusher.Flush() - - // Start notification handler for this session - done := make(chan struct{}) - defer close(done) - writeChan := make(chan any, 16) - - go func() { - for { - select { - case nt := <-session.notificationChannel: - select { - case writeChan <- &nt: - case <-done: - return - } - case <-done: - return - } - } - }() - - if s.listenHeartbeatInterval > 0 { - // heartbeat to keep the connection alive - go func() { - ticker := time.NewTicker(s.listenHeartbeatInterval) - defer ticker.Stop() - for { - select { - case <-ticker.C: - message := mcp.JSONRPCRequest{ - JSONRPC: "2.0", - ID: mcp.NewRequestId(s.nextRequestID(sessionID)), - Request: mcp.Request{ - Method: "ping", - }, - } - select { - case writeChan <- message: - case <-done: - return - } - case <-done: - return - } - } - }() - } - - // Keep the connection open until the client disconnects - // - // There's will a Available() check when handler ends, and it maybe race with Flush(), - // so we use a separate channel to send the data, inteading of flushing directly in other goroutine. - for { - select { - case data := <-writeChan: - if data == nil { - continue - } - if err := writeSSEEvent(w, data); err != nil { - s.logger.Errorf("Failed to write SSE event: %v", err) - return - } - flusher.Flush() - case <-r.Context().Done(): - return - } - } -} - -func (s *StreamableHTTPServer) handleDelete(w http.ResponseWriter, r *http.Request) { - // delete request terminate the session - sessionID := r.Header.Get(headerKeySessionID) - notAllowed, err := s.sessionIdManager.Terminate(sessionID) - if err != nil { - http.Error(w, fmt.Sprintf("Session termination failed: %v", err), http.StatusInternalServerError) - return - } - if notAllowed { - http.Error(w, "Session termination not allowed", http.StatusMethodNotAllowed) - return - } - - // remove the session relateddata from the sessionToolsStore - s.sessionTools.delete(sessionID) - - // remove current session's requstID information - s.sessionRequestIDs.Delete(sessionID) - - w.WriteHeader(http.StatusOK) -} - -func writeSSEEvent(w io.Writer, data any) error { - jsonData, err := json.Marshal(data) - if err != nil { - return fmt.Errorf("failed to marshal data: %w", err) - } - _, err = fmt.Fprintf(w, "event: message\ndata: %s\n\n", jsonData) - if err != nil { - return fmt.Errorf("failed to write SSE event: %w", err) - } - return nil -} - -// writeJSONRPCError writes a JSON-RPC error response with the given error details. -func (s *StreamableHTTPServer) writeJSONRPCError( - w http.ResponseWriter, - id any, - code int, - message string, -) { - response := createErrorResponse(id, code, message) - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusBadRequest) - err := json.NewEncoder(w).Encode(response) - if err != nil { - s.logger.Errorf("Failed to write JSONRPCError: %v", err) - } -} - -// nextRequestID gets the next incrementing requestID for the current session -func (s *StreamableHTTPServer) nextRequestID(sessionID string) int64 { - actual, _ := s.sessionRequestIDs.LoadOrStore(sessionID, new(atomic.Int64)) - counter := actual.(*atomic.Int64) - return counter.Add(1) -} - -// --- session --- - -type sessionToolsStore struct { - mu sync.RWMutex - tools map[string]map[string]ServerTool // sessionID -> toolName -> tool -} - -func newSessionToolsStore() *sessionToolsStore { - return &sessionToolsStore{ - tools: make(map[string]map[string]ServerTool), - } -} - -func (s *sessionToolsStore) get(sessionID string) map[string]ServerTool { - s.mu.RLock() - defer s.mu.RUnlock() - return s.tools[sessionID] -} - -func (s *sessionToolsStore) set(sessionID string, tools map[string]ServerTool) { - s.mu.Lock() - defer s.mu.Unlock() - s.tools[sessionID] = tools -} - -func (s *sessionToolsStore) delete(sessionID string) { - s.mu.Lock() - defer s.mu.Unlock() - delete(s.tools, sessionID) -} - -// streamableHttpSession is a session for streamable-http transport -// When in POST handlers(request/notification), it's ephemeral, and only exists in the life of the request handler. -// When in GET handlers(listening), it's a real session, and will be registered in the MCP server. -type streamableHttpSession struct { - sessionID string - notificationChannel chan mcp.JSONRPCNotification // server -> client notifications - tools *sessionToolsStore - upgradeToSSE atomic.Bool -} - -func newStreamableHttpSession(sessionID string, toolStore *sessionToolsStore) *streamableHttpSession { - return &streamableHttpSession{ - sessionID: sessionID, - notificationChannel: make(chan mcp.JSONRPCNotification, 100), - tools: toolStore, - } -} - -func (s *streamableHttpSession) SessionID() string { - return s.sessionID -} - -func (s *streamableHttpSession) NotificationChannel() chan<- mcp.JSONRPCNotification { - return s.notificationChannel -} - -func (s *streamableHttpSession) Initialize() { - // do nothing - // the session is ephemeral, no real initialized action needed -} - -func (s *streamableHttpSession) Initialized() bool { - // the session is ephemeral, no real initialized action needed - return true -} - -var _ ClientSession = (*streamableHttpSession)(nil) - -func (s *streamableHttpSession) GetSessionTools() map[string]ServerTool { - return s.tools.get(s.sessionID) -} - -func (s *streamableHttpSession) SetSessionTools(tools map[string]ServerTool) { - s.tools.set(s.sessionID, tools) -} - -var _ SessionWithTools = (*streamableHttpSession)(nil) - -func (s *streamableHttpSession) UpgradeToSSEWhenReceiveNotification() { - s.upgradeToSSE.Store(true) -} - -var _ SessionWithStreamableHTTPConfig = (*streamableHttpSession)(nil) - -// --- session id manager --- - -type SessionIdManager interface { - Generate() string - // Validate checks if a session ID is valid and not terminated. - // Returns isTerminated=true if the ID is valid but belongs to a terminated session. - // Returns err!=nil if the ID format is invalid or lookup failed. - Validate(sessionID string) (isTerminated bool, err error) - // Terminate marks a session ID as terminated. - // Returns isNotAllowed=true if the server policy prevents client termination. - // Returns err!=nil if the ID is invalid or termination failed. - Terminate(sessionID string) (isNotAllowed bool, err error) -} - -// StatelessSessionIdManager does nothing, which means it has no session management, which is stateless. -type StatelessSessionIdManager struct{} - -func (s *StatelessSessionIdManager) Generate() string { - return "" -} -func (s *StatelessSessionIdManager) Validate(sessionID string) (isTerminated bool, err error) { - // In stateless mode, ignore session IDs completely - don't validate or reject them - return false, nil -} -func (s *StatelessSessionIdManager) Terminate(sessionID string) (isNotAllowed bool, err error) { - return false, nil -} - -// InsecureStatefulSessionIdManager generate id with uuid -// It won't validate the id indeed, so it could be fake. -// For more secure session id, use a more complex generator, like a JWT. -type InsecureStatefulSessionIdManager struct{} - -const idPrefix = "mcp-session-" - -func (s *InsecureStatefulSessionIdManager) Generate() string { - return idPrefix + uuid.New().String() -} -func (s *InsecureStatefulSessionIdManager) Validate(sessionID string) (isTerminated bool, err error) { - // validate the session id is a valid uuid - if !strings.HasPrefix(sessionID, idPrefix) { - return false, fmt.Errorf("invalid session id: %s", sessionID) - } - if _, err := uuid.Parse(sessionID[len(idPrefix):]); err != nil { - return false, fmt.Errorf("invalid session id: %s", sessionID) - } - return false, nil -} -func (s *InsecureStatefulSessionIdManager) Terminate(sessionID string) (isNotAllowed bool, err error) { - return false, nil -} - -// NewTestStreamableHTTPServer creates a test server for testing purposes -func NewTestStreamableHTTPServer(server *MCPServer, opts ...StreamableHTTPOption) *httptest.Server { - sseServer := NewStreamableHTTPServer(server, opts...) - testServer := httptest.NewServer(sseServer) - return testServer -} diff --git a/vendor/github.com/mark3labs/mcp-go/util/logger.go b/vendor/github.com/mark3labs/mcp-go/util/logger.go deleted file mode 100644 index 8d7555ce35..0000000000 --- a/vendor/github.com/mark3labs/mcp-go/util/logger.go +++ /dev/null @@ -1,33 +0,0 @@ -package util - -import ( - "log" -) - -// Logger defines a minimal logging interface -type Logger interface { - Infof(format string, v ...any) - Errorf(format string, v ...any) -} - -// --- Standard Library Logger Wrapper --- - -// DefaultStdLogger implements Logger using the standard library's log.Logger. -func DefaultLogger() Logger { - return &stdLogger{ - logger: log.Default(), - } -} - -// stdLogger wraps the standard library's log.Logger. -type stdLogger struct { - logger *log.Logger -} - -func (l *stdLogger) Infof(format string, v ...any) { - l.logger.Printf("INFO: "+format, v...) -} - -func (l *stdLogger) Errorf(format string, v ...any) { - l.logger.Printf("ERROR: "+format, v...) -} diff --git a/vendor/github.com/mark3labs/mcp-go/LICENSE b/vendor/github.com/shibukawa/configdir/LICENSE similarity index 95% rename from vendor/github.com/mark3labs/mcp-go/LICENSE rename to vendor/github.com/shibukawa/configdir/LICENSE index 3d48435454..b20af456a1 100644 --- a/vendor/github.com/mark3labs/mcp-go/LICENSE +++ b/vendor/github.com/shibukawa/configdir/LICENSE @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (c) 2024 Anthropic, PBC +Copyright (c) 2016 shibukawa Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/shibukawa/configdir/README.rst b/vendor/github.com/shibukawa/configdir/README.rst new file mode 100644 index 0000000000..99906697da --- /dev/null +++ b/vendor/github.com/shibukawa/configdir/README.rst @@ -0,0 +1,111 @@ +configdir for Golang +===================== + +Multi platform library of configuration directory for Golang. + +This library helps to get regular directories for configuration files or cache files that matches target operationg system's convention. + +It assumes the following folders are standard paths of each environment: + +.. list-table:: + :header-rows: 1 + + - * + * Windows: + * Linux/BSDs: + * MacOSX: + - * System level configuration folder + * ``%PROGRAMDATA%`` (``C:\\ProgramData``) + * ``${XDG_CONFIG_DIRS}`` (``/etc/xdg``) + * ``/Library/Application Support`` + - * User level configuration folder + * ``%APPDATA%`` (``C:\\Users\\\\AppData\\Roaming``) + * ``${XDG_CONFIG_HOME}`` (``${HOME}/.config``) + * ``${HOME}/Library/Application Support`` + - * User wide cache folder + * ``%LOCALAPPDATA%`` ``(C:\\Users\\\\AppData\\Local)`` + * ``${XDG_CACHE_HOME}`` (``${HOME}/.cache``) + * ``${HOME}/Library/Caches`` + +Examples +------------ + +Getting Configuration +~~~~~~~~~~~~~~~~~~~~~~~~ + +``configdir.ConfigDir.QueryFolderContainsFile()`` searches files in the following order: + +* Local path (if you add the path via LocalPath parameter) +* User level configuration folder(e.g. ``$HOME/.config///setting.json`` in Linux) +* System level configuration folder(e.g. ``/etc/xdg///setting.json`` in Linux) + +``configdir.Config`` provides some convenient methods(``ReadFile``, ``WriteFile`` and so on). + +.. code-block:: go + + var config Config + + configDirs := configdir.New("vendor-name", "application-name") + // optional: local path has the highest priority + configDirs.LocalPath, _ = filepath.Abs(".") + folder := configDirs.QueryFolderContainsFile("setting.json") + if folder != nil { + data, _ := folder.ReadFile("setting.json") + json.Unmarshal(data, &config) + } else { + config = DefaultConfig + } + +Write Configuration +~~~~~~~~~~~~~~~~~~~~~~ + +When storing configuration, get configuration folder by using ``configdir.ConfigDir.QueryFolders()`` method. + +.. code-block:: go + + configDirs := configdir.New("vendor-name", "application-name") + + var config Config + data, _ := json.Marshal(&config) + + // Stores to local folder + folders := configDirs.QueryFolders(configdir.Local) + folders[0].WriteFile("setting.json", data) + + // Stores to user folder + folders = configDirs.QueryFolders(configdir.Global) + folders[0].WriteFile("setting.json", data) + + // Stores to system folder + folders = configDirs.QueryFolders(configdir.System) + folders[0].WriteFile("setting.json", data) + +Getting Cache Folder +~~~~~~~~~~~~~~~~~~~~~~ + +It is similar to the above example, but returns cache folder. + +.. code-block:: go + + configDirs := configdir.New("vendor-name", "application-name") + cache := configDirs.QueryCacheFolder() + + resp, err := http.Get("http://examples.com/sdk.zip") + if err != nil { + log.Fatal(err) + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + + cache.WriteFile("sdk.zip", body) + +Document +------------ + +https://godoc.org/github.com/shibukawa/configdir + +License +------------ + +MIT + diff --git a/vendor/github.com/shibukawa/configdir/config.go b/vendor/github.com/shibukawa/configdir/config.go new file mode 100644 index 0000000000..8a20e54b59 --- /dev/null +++ b/vendor/github.com/shibukawa/configdir/config.go @@ -0,0 +1,160 @@ +// configdir provides access to configuration folder in each platforms. +// +// System wide configuration folders: +// +// - Windows: %PROGRAMDATA% (C:\ProgramData) +// - Linux/BSDs: ${XDG_CONFIG_DIRS} (/etc/xdg) +// - MacOSX: "/Library/Application Support" +// +// User wide configuration folders: +// +// - Windows: %APPDATA% (C:\Users\\AppData\Roaming) +// - Linux/BSDs: ${XDG_CONFIG_HOME} (${HOME}/.config) +// - MacOSX: "${HOME}/Library/Application Support" +// +// User wide cache folders: +// +// - Windows: %LOCALAPPDATA% (C:\Users\\AppData\Local) +// - Linux/BSDs: ${XDG_CACHE_HOME} (${HOME}/.cache) +// - MacOSX: "${HOME}/Library/Caches" +// +// configdir returns paths inside the above folders. + +package configdir + +import ( + "io/ioutil" + "os" + "path/filepath" +) + +type ConfigType int + +const ( + System ConfigType = iota + Global + All + Existing + Local + Cache +) + +// Config represents each folder +type Config struct { + Path string + Type ConfigType +} + +func (c Config) Open(fileName string) (*os.File, error) { + return os.Open(filepath.Join(c.Path, fileName)) +} + +func (c Config) Create(fileName string) (*os.File, error) { + err := c.CreateParentDir(fileName) + if err != nil { + return nil, err + } + return os.Create(filepath.Join(c.Path, fileName)) +} + +func (c Config) ReadFile(fileName string) ([]byte, error) { + return ioutil.ReadFile(filepath.Join(c.Path, fileName)) +} + +// CreateParentDir creates the parent directory of fileName inside c. fileName +// is a relative path inside c, containing zero or more path separators. +func (c Config) CreateParentDir(fileName string) error { + return os.MkdirAll(filepath.Dir(filepath.Join(c.Path, fileName)), 0755) +} + +func (c Config) WriteFile(fileName string, data []byte) error { + err := c.CreateParentDir(fileName) + if err != nil { + return err + } + return ioutil.WriteFile(filepath.Join(c.Path, fileName), data, 0644) +} + +func (c Config) MkdirAll() error { + return os.MkdirAll(c.Path, 0755) +} + +func (c Config) Exists(fileName string) bool { + _, err := os.Stat(filepath.Join(c.Path, fileName)) + return !os.IsNotExist(err) +} + +// ConfigDir keeps setting for querying folders. +type ConfigDir struct { + VendorName string + ApplicationName string + LocalPath string +} + +func New(vendorName, applicationName string) ConfigDir { + return ConfigDir{ + VendorName: vendorName, + ApplicationName: applicationName, + } +} + +func (c ConfigDir) joinPath(root string) string { + if c.VendorName != "" && hasVendorName { + return filepath.Join(root, c.VendorName, c.ApplicationName) + } + return filepath.Join(root, c.ApplicationName) +} + +func (c ConfigDir) QueryFolders(configType ConfigType) []*Config { + if configType == Cache { + return []*Config{c.QueryCacheFolder()} + } + var result []*Config + if c.LocalPath != "" && configType != System && configType != Global { + result = append(result, &Config{ + Path: c.LocalPath, + Type: Local, + }) + } + if configType != System && configType != Local { + result = append(result, &Config{ + Path: c.joinPath(globalSettingFolder), + Type: Global, + }) + } + if configType != Global && configType != Local { + for _, root := range systemSettingFolders { + result = append(result, &Config{ + Path: c.joinPath(root), + Type: System, + }) + } + } + if configType != Existing { + return result + } + var existing []*Config + for _, entry := range result { + if _, err := os.Stat(entry.Path); !os.IsNotExist(err) { + existing = append(existing, entry) + } + } + return existing +} + +func (c ConfigDir) QueryFolderContainsFile(fileName string) *Config { + configs := c.QueryFolders(Existing) + for _, config := range configs { + if _, err := os.Stat(filepath.Join(config.Path, fileName)); !os.IsNotExist(err) { + return config + } + } + return nil +} + +func (c ConfigDir) QueryCacheFolder() *Config { + return &Config{ + Path: c.joinPath(cacheFolder), + Type: Cache, + } +} diff --git a/vendor/github.com/shibukawa/configdir/config_darwin.go b/vendor/github.com/shibukawa/configdir/config_darwin.go new file mode 100644 index 0000000000..d668507a7e --- /dev/null +++ b/vendor/github.com/shibukawa/configdir/config_darwin.go @@ -0,0 +1,8 @@ +package configdir + +import "os" + +var hasVendorName = true +var systemSettingFolders = []string{"/Library/Application Support"} +var globalSettingFolder = os.Getenv("HOME") + "/Library/Application Support" +var cacheFolder = os.Getenv("HOME") + "/Library/Caches" diff --git a/vendor/github.com/shibukawa/configdir/config_windows.go b/vendor/github.com/shibukawa/configdir/config_windows.go new file mode 100644 index 0000000000..0984821778 --- /dev/null +++ b/vendor/github.com/shibukawa/configdir/config_windows.go @@ -0,0 +1,8 @@ +package configdir + +import "os" + +var hasVendorName = true +var systemSettingFolders = []string{os.Getenv("PROGRAMDATA")} +var globalSettingFolder = os.Getenv("APPDATA") +var cacheFolder = os.Getenv("LOCALAPPDATA") diff --git a/vendor/github.com/shibukawa/configdir/config_xdg.go b/vendor/github.com/shibukawa/configdir/config_xdg.go new file mode 100644 index 0000000000..026ca68a0b --- /dev/null +++ b/vendor/github.com/shibukawa/configdir/config_xdg.go @@ -0,0 +1,34 @@ +// +build !windows,!darwin + +package configdir + +import ( + "os" + "path/filepath" + "strings" +) + +// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + +var hasVendorName = true +var systemSettingFolders []string +var globalSettingFolder string +var cacheFolder string + +func init() { + if os.Getenv("XDG_CONFIG_HOME") != "" { + globalSettingFolder = os.Getenv("XDG_CONFIG_HOME") + } else { + globalSettingFolder = filepath.Join(os.Getenv("HOME"), ".config") + } + if os.Getenv("XDG_CONFIG_DIRS") != "" { + systemSettingFolders = strings.Split(os.Getenv("XDG_CONFIG_DIRS"), ":") + } else { + systemSettingFolders = []string{"/etc/xdg"} + } + if os.Getenv("XDG_CACHE_HOME") != "" { + cacheFolder = os.Getenv("XDG_CACHE_HOME") + } else { + cacheFolder = filepath.Join(os.Getenv("HOME"), ".cache") + } +} diff --git a/vendor/github.com/spf13/cast/.editorconfig b/vendor/github.com/spf13/cast/.editorconfig deleted file mode 100644 index a85749f190..0000000000 --- a/vendor/github.com/spf13/cast/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_size = 4 -indent_style = space -insert_final_newline = true -trim_trailing_whitespace = true - -[*.go] -indent_style = tab - -[{*.yml,*.yaml}] -indent_size = 2 diff --git a/vendor/github.com/spf13/cast/.golangci.yaml b/vendor/github.com/spf13/cast/.golangci.yaml deleted file mode 100644 index e00fd47aa2..0000000000 --- a/vendor/github.com/spf13/cast/.golangci.yaml +++ /dev/null @@ -1,39 +0,0 @@ -version: "2" - -run: - timeout: 10m - -linters: - enable: - - errcheck - - govet - - ineffassign - - misspell - - nolintlint - # - revive - - unused - - disable: - - staticcheck - - settings: - misspell: - locale: US - nolintlint: - allow-unused: false # report any unused nolint directives - require-specific: false # don't require nolint directives to be specific about which linter is being skipped - -formatters: - enable: - - gci - - gofmt - # - gofumpt - - goimports - # - golines - - settings: - gci: - sections: - - standard - - default - - localmodule diff --git a/vendor/github.com/spf13/cast/.travis.yml b/vendor/github.com/spf13/cast/.travis.yml new file mode 100644 index 0000000000..6420d1c27f --- /dev/null +++ b/vendor/github.com/spf13/cast/.travis.yml @@ -0,0 +1,15 @@ +language: go +env: + - GO111MODULE=on +sudo: required +go: + - "1.11.x" + - tip +os: + - linux +matrix: + allow_failures: + - go: tip + fast_finish: true +script: + - make check diff --git a/vendor/github.com/spf13/cast/Makefile b/vendor/github.com/spf13/cast/Makefile index f01a5dbb6e..7ccf8930b5 100644 --- a/vendor/github.com/spf13/cast/Makefile +++ b/vendor/github.com/spf13/cast/Makefile @@ -1,4 +1,4 @@ -GOVERSION := $(shell go version | cut -d ' ' -f 3 | cut -d '.' -f 2) +# A Self-Documenting Makefile: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html .PHONY: check fmt lint test test-race vet test-cover-html help .DEFAULT_GOAL := help @@ -12,13 +12,11 @@ test-race: ## Run tests with race detector go test -race ./... fmt: ## Run gofmt linter -ifeq "$(GOVERSION)" "12" @for d in `go list` ; do \ if [ "`gofmt -l -s $$GOPATH/src/$$d | tee /dev/stderr`" ]; then \ echo "^ improperly formatted go files" && echo && exit 1; \ fi \ done -endif lint: ## Run golint linter @for d in `go list` ; do \ diff --git a/vendor/github.com/spf13/cast/README.md b/vendor/github.com/spf13/cast/README.md index c58eccb3fd..e6939397dd 100644 --- a/vendor/github.com/spf13/cast/README.md +++ b/vendor/github.com/spf13/cast/README.md @@ -1,9 +1,8 @@ -# cast - -[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/ci.yaml?style=flat-square)](https://github.com/spf13/cast/actions/workflows/ci.yaml) -[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat-square)](https://pkg.go.dev/mod/github.com/spf13/cast) -![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/spf13/cast?style=flat-square&color=61CFDD) -[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/spf13/cast/badge?style=flat-square)](https://deps.dev/go/github.com%252Fspf13%252Fcast) +cast +==== +[![GoDoc](https://godoc.org/github.com/spf13/cast?status.svg)](https://godoc.org/github.com/spf13/cast) +[![Build Status](https://api.travis-ci.org/spf13/cast.svg?branch=master)](https://travis-ci.org/spf13/cast) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast) Easy and safe casting from one type to another in Go @@ -18,7 +17,7 @@ interface into a bool, etc. Cast does this intelligently when an obvious conversion is possible. It doesn’t make any attempts to guess what you meant, for example you can only convert a string to an int when it is a string representation of an int such as “8”. Cast was developed for use in -[Hugo](https://gohugo.io), a website engine which uses YAML, TOML or JSON +[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON for meta data. ## Why use Cast? @@ -74,6 +73,3 @@ the code for a complete set. cast.ToInt(eight) // 8 cast.ToInt(nil) // 0 -## License - -The project is licensed under the [MIT License](LICENSE). diff --git a/vendor/github.com/spf13/cast/alias.go b/vendor/github.com/spf13/cast/alias.go deleted file mode 100644 index 855d60005d..0000000000 --- a/vendor/github.com/spf13/cast/alias.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright © 2014 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. -package cast - -import ( - "reflect" - "slices" -) - -var kindNames = []string{ - reflect.String: "string", - reflect.Bool: "bool", - reflect.Int: "int", - reflect.Int8: "int8", - reflect.Int16: "int16", - reflect.Int32: "int32", - reflect.Int64: "int64", - reflect.Uint: "uint", - reflect.Uint8: "uint8", - reflect.Uint16: "uint16", - reflect.Uint32: "uint32", - reflect.Uint64: "uint64", - reflect.Float32: "float32", - reflect.Float64: "float64", -} - -var kinds = map[reflect.Kind]func(reflect.Value) any{ - reflect.String: func(v reflect.Value) any { return v.String() }, - reflect.Bool: func(v reflect.Value) any { return v.Bool() }, - reflect.Int: func(v reflect.Value) any { return int(v.Int()) }, - reflect.Int8: func(v reflect.Value) any { return int8(v.Int()) }, - reflect.Int16: func(v reflect.Value) any { return int16(v.Int()) }, - reflect.Int32: func(v reflect.Value) any { return int32(v.Int()) }, - reflect.Int64: func(v reflect.Value) any { return v.Int() }, - reflect.Uint: func(v reflect.Value) any { return uint(v.Uint()) }, - reflect.Uint8: func(v reflect.Value) any { return uint8(v.Uint()) }, - reflect.Uint16: func(v reflect.Value) any { return uint16(v.Uint()) }, - reflect.Uint32: func(v reflect.Value) any { return uint32(v.Uint()) }, - reflect.Uint64: func(v reflect.Value) any { return v.Uint() }, - reflect.Float32: func(v reflect.Value) any { return float32(v.Float()) }, - reflect.Float64: func(v reflect.Value) any { return v.Float() }, -} - -// resolveAlias attempts to resolve a named type to its underlying basic type (if possible). -// -// Pointers are expected to be indirected by this point. -func resolveAlias(i any) (any, bool) { - if i == nil { - return nil, false - } - - t := reflect.TypeOf(i) - - // Not a named type - if t.Name() == "" || slices.Contains(kindNames, t.Name()) { - return i, false - } - - resolve, ok := kinds[t.Kind()] - if !ok { // Not a supported kind - return i, false - } - - v := reflect.ValueOf(i) - - return resolve(v), true -} diff --git a/vendor/github.com/spf13/cast/basic.go b/vendor/github.com/spf13/cast/basic.go deleted file mode 100644 index fa330e207a..0000000000 --- a/vendor/github.com/spf13/cast/basic.go +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright © 2014 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package cast - -import ( - "encoding/json" - "fmt" - "html/template" - "strconv" - "time" -) - -// ToBoolE casts any value to a bool type. -func ToBoolE(i any) (bool, error) { - i, _ = indirect(i) - - switch b := i.(type) { - case bool: - return b, nil - case nil: - return false, nil - case int: - return b != 0, nil - case int8: - return b != 0, nil - case int16: - return b != 0, nil - case int32: - return b != 0, nil - case int64: - return b != 0, nil - case uint: - return b != 0, nil - case uint8: - return b != 0, nil - case uint16: - return b != 0, nil - case uint32: - return b != 0, nil - case uint64: - return b != 0, nil - case float32: - return b != 0, nil - case float64: - return b != 0, nil - case time.Duration: - return b != 0, nil - case string: - return strconv.ParseBool(b) - case json.Number: - v, err := ToInt64E(b) - if err == nil { - return v != 0, nil - } - - return false, fmt.Errorf(errorMsg, i, i, false) - default: - if i, ok := resolveAlias(i); ok { - return ToBoolE(i) - } - - return false, fmt.Errorf(errorMsg, i, i, false) - } -} - -// ToStringE casts any value to a string type. -func ToStringE(i any) (string, error) { - switch s := i.(type) { - case string: - return s, nil - case bool: - return strconv.FormatBool(s), nil - case float64: - return strconv.FormatFloat(s, 'f', -1, 64), nil - case float32: - return strconv.FormatFloat(float64(s), 'f', -1, 32), nil - case int: - return strconv.Itoa(s), nil - case int8: - return strconv.FormatInt(int64(s), 10), nil - case int16: - return strconv.FormatInt(int64(s), 10), nil - case int32: - return strconv.FormatInt(int64(s), 10), nil - case int64: - return strconv.FormatInt(s, 10), nil - case uint: - return strconv.FormatUint(uint64(s), 10), nil - case uint8: - return strconv.FormatUint(uint64(s), 10), nil - case uint16: - return strconv.FormatUint(uint64(s), 10), nil - case uint32: - return strconv.FormatUint(uint64(s), 10), nil - case uint64: - return strconv.FormatUint(s, 10), nil - case json.Number: - return s.String(), nil - case []byte: - return string(s), nil - case template.HTML: - return string(s), nil - case template.URL: - return string(s), nil - case template.JS: - return string(s), nil - case template.CSS: - return string(s), nil - case template.HTMLAttr: - return string(s), nil - case nil: - return "", nil - case fmt.Stringer: - return s.String(), nil - case error: - return s.Error(), nil - default: - if i, ok := indirect(i); ok { - return ToStringE(i) - } - - if i, ok := resolveAlias(i); ok { - return ToStringE(i) - } - - return "", fmt.Errorf(errorMsg, i, i, "") - } -} diff --git a/vendor/github.com/spf13/cast/cast.go b/vendor/github.com/spf13/cast/cast.go index 8d85539b35..9fba638d46 100644 --- a/vendor/github.com/spf13/cast/cast.go +++ b/vendor/github.com/spf13/cast/cast.go @@ -8,77 +8,164 @@ package cast import "time" -const errorMsg = "unable to cast %#v of type %T to %T" -const errorMsgWith = "unable to cast %#v of type %T to %T: %w" +// ToBool casts an interface to a bool type. +func ToBool(i interface{}) bool { + v, _ := ToBoolE(i) + return v +} -// Basic is a type parameter constraint for functions accepting basic types. -// -// It represents the supported basic types this package can cast to. -type Basic interface { - string | bool | Number | time.Time | time.Duration -} - -// ToE casts any value to a [Basic] type. -func ToE[T Basic](i any) (T, error) { - var t T - - var v any - var err error - - switch any(t).(type) { - case string: - v, err = ToStringE(i) - case bool: - v, err = ToBoolE(i) - case int: - v, err = toNumberE[int](i, parseInt[int]) - case int8: - v, err = toNumberE[int8](i, parseInt[int8]) - case int16: - v, err = toNumberE[int16](i, parseInt[int16]) - case int32: - v, err = toNumberE[int32](i, parseInt[int32]) - case int64: - v, err = toNumberE[int64](i, parseInt[int64]) - case uint: - v, err = toUnsignedNumberE[uint](i, parseUint[uint]) - case uint8: - v, err = toUnsignedNumberE[uint8](i, parseUint[uint8]) - case uint16: - v, err = toUnsignedNumberE[uint16](i, parseUint[uint16]) - case uint32: - v, err = toUnsignedNumberE[uint32](i, parseUint[uint32]) - case uint64: - v, err = toUnsignedNumberE[uint64](i, parseUint[uint64]) - case float32: - v, err = toNumberE[float32](i, parseFloat[float32]) - case float64: - v, err = toNumberE[float64](i, parseFloat[float64]) - case time.Time: - v, err = ToTimeE(i) - case time.Duration: - v, err = ToDurationE(i) - } - - if err != nil { - return t, err - } - - return v.(T), nil -} - -// Must is a helper that wraps a call to a cast function and panics if the error is non-nil. -func Must[T any](i any, err error) T { - if err != nil { - panic(err) - } - - return i.(T) -} - -// To casts any value to a [Basic] type. -func To[T Basic](i any) T { - v, _ := ToE[T](i) +// ToTime casts an interface to a time.Time type. +func ToTime(i interface{}) time.Time { + v, _ := ToTimeE(i) + return v +} + +// ToDuration casts an interface to a time.Duration type. +func ToDuration(i interface{}) time.Duration { + v, _ := ToDurationE(i) + return v +} + +// ToFloat64 casts an interface to a float64 type. +func ToFloat64(i interface{}) float64 { + v, _ := ToFloat64E(i) + return v +} + +// ToFloat32 casts an interface to a float32 type. +func ToFloat32(i interface{}) float32 { + v, _ := ToFloat32E(i) + return v +} + +// ToInt64 casts an interface to an int64 type. +func ToInt64(i interface{}) int64 { + v, _ := ToInt64E(i) + return v +} + +// ToInt32 casts an interface to an int32 type. +func ToInt32(i interface{}) int32 { + v, _ := ToInt32E(i) + return v +} + +// ToInt16 casts an interface to an int16 type. +func ToInt16(i interface{}) int16 { + v, _ := ToInt16E(i) + return v +} + +// ToInt8 casts an interface to an int8 type. +func ToInt8(i interface{}) int8 { + v, _ := ToInt8E(i) + return v +} + +// ToInt casts an interface to an int type. +func ToInt(i interface{}) int { + v, _ := ToIntE(i) + return v +} + +// ToUint casts an interface to a uint type. +func ToUint(i interface{}) uint { + v, _ := ToUintE(i) + return v +} + +// ToUint64 casts an interface to a uint64 type. +func ToUint64(i interface{}) uint64 { + v, _ := ToUint64E(i) + return v +} + +// ToUint32 casts an interface to a uint32 type. +func ToUint32(i interface{}) uint32 { + v, _ := ToUint32E(i) + return v +} + +// ToUint16 casts an interface to a uint16 type. +func ToUint16(i interface{}) uint16 { + v, _ := ToUint16E(i) + return v +} + +// ToUint8 casts an interface to a uint8 type. +func ToUint8(i interface{}) uint8 { + v, _ := ToUint8E(i) + return v +} + +// ToString casts an interface to a string type. +func ToString(i interface{}) string { + v, _ := ToStringE(i) + return v +} + +// ToStringMapString casts an interface to a map[string]string type. +func ToStringMapString(i interface{}) map[string]string { + v, _ := ToStringMapStringE(i) + return v +} + +// ToStringMapStringSlice casts an interface to a map[string][]string type. +func ToStringMapStringSlice(i interface{}) map[string][]string { + v, _ := ToStringMapStringSliceE(i) + return v +} + +// ToStringMapBool casts an interface to a map[string]bool type. +func ToStringMapBool(i interface{}) map[string]bool { + v, _ := ToStringMapBoolE(i) + return v +} + +// ToStringMapInt casts an interface to a map[string]int type. +func ToStringMapInt(i interface{}) map[string]int { + v, _ := ToStringMapIntE(i) + return v +} + +// ToStringMapInt64 casts an interface to a map[string]int64 type. +func ToStringMapInt64(i interface{}) map[string]int64 { + v, _ := ToStringMapInt64E(i) + return v +} + +// ToStringMap casts an interface to a map[string]interface{} type. +func ToStringMap(i interface{}) map[string]interface{} { + v, _ := ToStringMapE(i) + return v +} + +// ToSlice casts an interface to a []interface{} type. +func ToSlice(i interface{}) []interface{} { + v, _ := ToSliceE(i) + return v +} + +// ToBoolSlice casts an interface to a []bool type. +func ToBoolSlice(i interface{}) []bool { + v, _ := ToBoolSliceE(i) + return v +} + +// ToStringSlice casts an interface to a []string type. +func ToStringSlice(i interface{}) []string { + v, _ := ToStringSliceE(i) + return v +} + +// ToIntSlice casts an interface to a []int type. +func ToIntSlice(i interface{}) []int { + v, _ := ToIntSliceE(i) + return v +} +// ToDurationSlice casts an interface to a []time.Duration type. +func ToDurationSlice(i interface{}) []time.Duration { + v, _ := ToDurationSliceE(i) return v } diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go new file mode 100644 index 0000000000..a4859fb0af --- /dev/null +++ b/vendor/github.com/spf13/cast/caste.go @@ -0,0 +1,1249 @@ +// Copyright © 2014 Steve Francia . +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file. + +package cast + +import ( + "encoding/json" + "errors" + "fmt" + "html/template" + "reflect" + "strconv" + "strings" + "time" +) + +var errNegativeNotAllowed = errors.New("unable to cast negative value") + +// ToTimeE casts an interface to a time.Time type. +func ToTimeE(i interface{}) (tim time.Time, err error) { + i = indirect(i) + + switch v := i.(type) { + case time.Time: + return v, nil + case string: + return StringToDate(v) + case int: + return time.Unix(int64(v), 0), nil + case int64: + return time.Unix(v, 0), nil + case int32: + return time.Unix(int64(v), 0), nil + case uint: + return time.Unix(int64(v), 0), nil + case uint64: + return time.Unix(int64(v), 0), nil + case uint32: + return time.Unix(int64(v), 0), nil + default: + return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i) + } +} + +// ToDurationE casts an interface to a time.Duration type. +func ToDurationE(i interface{}) (d time.Duration, err error) { + i = indirect(i) + + switch s := i.(type) { + case time.Duration: + return s, nil + case int, int64, int32, int16, int8, uint, uint64, uint32, uint16, uint8: + d = time.Duration(ToInt64(s)) + return + case float32, float64: + d = time.Duration(ToFloat64(s)) + return + case string: + if strings.ContainsAny(s, "nsuµmh") { + d, err = time.ParseDuration(s) + } else { + d, err = time.ParseDuration(s + "ns") + } + return + default: + err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i) + return + } +} + +// ToBoolE casts an interface to a bool type. +func ToBoolE(i interface{}) (bool, error) { + i = indirect(i) + + switch b := i.(type) { + case bool: + return b, nil + case nil: + return false, nil + case int: + if i.(int) != 0 { + return true, nil + } + return false, nil + case string: + return strconv.ParseBool(i.(string)) + default: + return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i) + } +} + +// ToFloat64E casts an interface to a float64 type. +func ToFloat64E(i interface{}) (float64, error) { + i = indirect(i) + + switch s := i.(type) { + case float64: + return s, nil + case float32: + return float64(s), nil + case int: + return float64(s), nil + case int64: + return float64(s), nil + case int32: + return float64(s), nil + case int16: + return float64(s), nil + case int8: + return float64(s), nil + case uint: + return float64(s), nil + case uint64: + return float64(s), nil + case uint32: + return float64(s), nil + case uint16: + return float64(s), nil + case uint8: + return float64(s), nil + case string: + v, err := strconv.ParseFloat(s, 64) + if err == nil { + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) + } +} + +// ToFloat32E casts an interface to a float32 type. +func ToFloat32E(i interface{}) (float32, error) { + i = indirect(i) + + switch s := i.(type) { + case float64: + return float32(s), nil + case float32: + return s, nil + case int: + return float32(s), nil + case int64: + return float32(s), nil + case int32: + return float32(s), nil + case int16: + return float32(s), nil + case int8: + return float32(s), nil + case uint: + return float32(s), nil + case uint64: + return float32(s), nil + case uint32: + return float32(s), nil + case uint16: + return float32(s), nil + case uint8: + return float32(s), nil + case string: + v, err := strconv.ParseFloat(s, 32) + if err == nil { + return float32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) + } +} + +// ToInt64E casts an interface to an int64 type. +func ToInt64E(i interface{}) (int64, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return int64(s), nil + case int64: + return s, nil + case int32: + return int64(s), nil + case int16: + return int64(s), nil + case int8: + return int64(s), nil + case uint: + return int64(s), nil + case uint64: + return int64(s), nil + case uint32: + return int64(s), nil + case uint16: + return int64(s), nil + case uint8: + return int64(s), nil + case float64: + return int64(s), nil + case float32: + return int64(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) + } +} + +// ToInt32E casts an interface to an int32 type. +func ToInt32E(i interface{}) (int32, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return int32(s), nil + case int64: + return int32(s), nil + case int32: + return s, nil + case int16: + return int32(s), nil + case int8: + return int32(s), nil + case uint: + return int32(s), nil + case uint64: + return int32(s), nil + case uint32: + return int32(s), nil + case uint16: + return int32(s), nil + case uint8: + return int32(s), nil + case float64: + return int32(s), nil + case float32: + return int32(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) + } +} + +// ToInt16E casts an interface to an int16 type. +func ToInt16E(i interface{}) (int16, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return int16(s), nil + case int64: + return int16(s), nil + case int32: + return int16(s), nil + case int16: + return s, nil + case int8: + return int16(s), nil + case uint: + return int16(s), nil + case uint64: + return int16(s), nil + case uint32: + return int16(s), nil + case uint16: + return int16(s), nil + case uint8: + return int16(s), nil + case float64: + return int16(s), nil + case float32: + return int16(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int16(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) + } +} + +// ToInt8E casts an interface to an int8 type. +func ToInt8E(i interface{}) (int8, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return int8(s), nil + case int64: + return int8(s), nil + case int32: + return int8(s), nil + case int16: + return int8(s), nil + case int8: + return s, nil + case uint: + return int8(s), nil + case uint64: + return int8(s), nil + case uint32: + return int8(s), nil + case uint16: + return int8(s), nil + case uint8: + return int8(s), nil + case float64: + return int8(s), nil + case float32: + return int8(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int8(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) + } +} + +// ToIntE casts an interface to an int type. +func ToIntE(i interface{}) (int, error) { + i = indirect(i) + + switch s := i.(type) { + case int: + return s, nil + case int64: + return int(s), nil + case int32: + return int(s), nil + case int16: + return int(s), nil + case int8: + return int(s), nil + case uint: + return int(s), nil + case uint64: + return int(s), nil + case uint32: + return int(s), nil + case uint16: + return int(s), nil + case uint8: + return int(s), nil + case float64: + return int(s), nil + case float32: + return int(s), nil + case string: + v, err := strconv.ParseInt(s, 0, 0) + if err == nil { + return int(v), nil + } + return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) + } +} + +// ToUintE casts an interface to a uint type. +func ToUintE(i interface{}) (uint, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 0) + if err == nil { + return uint(v), nil + } + return 0, fmt.Errorf("unable to cast %#v to uint: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case uint: + return s, nil + case uint64: + return uint(s), nil + case uint32: + return uint(s), nil + case uint16: + return uint(s), nil + case uint8: + return uint(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i) + } +} + +// ToUint64E casts an interface to a uint64 type. +func ToUint64E(i interface{}) (uint64, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 64) + if err == nil { + return v, nil + } + return 0, fmt.Errorf("unable to cast %#v to uint64: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case uint: + return uint64(s), nil + case uint64: + return s, nil + case uint32: + return uint64(s), nil + case uint16: + return uint64(s), nil + case uint8: + return uint64(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint64(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i) + } +} + +// ToUint32E casts an interface to a uint32 type. +func ToUint32E(i interface{}) (uint32, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 32) + if err == nil { + return uint32(v), nil + } + return 0, fmt.Errorf("unable to cast %#v to uint32: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case uint: + return uint32(s), nil + case uint64: + return uint32(s), nil + case uint32: + return s, nil + case uint16: + return uint32(s), nil + case uint8: + return uint32(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint32(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i) + } +} + +// ToUint16E casts an interface to a uint16 type. +func ToUint16E(i interface{}) (uint16, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 16) + if err == nil { + return uint16(v), nil + } + return 0, fmt.Errorf("unable to cast %#v to uint16: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case uint: + return uint16(s), nil + case uint64: + return uint16(s), nil + case uint32: + return uint16(s), nil + case uint16: + return s, nil + case uint8: + return uint16(s), nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint16(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i) + } +} + +// ToUint8E casts an interface to a uint type. +func ToUint8E(i interface{}) (uint8, error) { + i = indirect(i) + + switch s := i.(type) { + case string: + v, err := strconv.ParseUint(s, 0, 8) + if err == nil { + return uint8(v), nil + } + return 0, fmt.Errorf("unable to cast %#v to uint8: %s", i, err) + case int: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int16: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case int8: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case uint: + return uint8(s), nil + case uint64: + return uint8(s), nil + case uint32: + return uint8(s), nil + case uint16: + return uint8(s), nil + case uint8: + return s, nil + case float64: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case float32: + if s < 0 { + return 0, errNegativeNotAllowed + } + return uint8(s), nil + case bool: + if s { + return 1, nil + } + return 0, nil + case nil: + return 0, nil + default: + return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i) + } +} + +// From html/template/content.go +// Copyright 2011 The Go Authors. All rights reserved. +// indirect returns the value, after dereferencing as many times +// as necessary to reach the base type (or nil). +func indirect(a interface{}) interface{} { + if a == nil { + return nil + } + if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr { + // Avoid creating a reflect.Value if it's not a pointer. + return a + } + v := reflect.ValueOf(a) + for v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + return v.Interface() +} + +// From html/template/content.go +// Copyright 2011 The Go Authors. All rights reserved. +// indirectToStringerOrError returns the value, after dereferencing as many times +// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer +// or error, +func indirectToStringerOrError(a interface{}) interface{} { + if a == nil { + return nil + } + + var errorType = reflect.TypeOf((*error)(nil)).Elem() + var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() + + v := reflect.ValueOf(a) + for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { + v = v.Elem() + } + return v.Interface() +} + +// ToStringE casts an interface to a string type. +func ToStringE(i interface{}) (string, error) { + i = indirectToStringerOrError(i) + + switch s := i.(type) { + case string: + return s, nil + case bool: + return strconv.FormatBool(s), nil + case float64: + return strconv.FormatFloat(s, 'f', -1, 64), nil + case float32: + return strconv.FormatFloat(float64(s), 'f', -1, 32), nil + case int: + return strconv.Itoa(s), nil + case int64: + return strconv.FormatInt(s, 10), nil + case int32: + return strconv.Itoa(int(s)), nil + case int16: + return strconv.FormatInt(int64(s), 10), nil + case int8: + return strconv.FormatInt(int64(s), 10), nil + case uint: + return strconv.FormatInt(int64(s), 10), nil + case uint64: + return strconv.FormatInt(int64(s), 10), nil + case uint32: + return strconv.FormatInt(int64(s), 10), nil + case uint16: + return strconv.FormatInt(int64(s), 10), nil + case uint8: + return strconv.FormatInt(int64(s), 10), nil + case []byte: + return string(s), nil + case template.HTML: + return string(s), nil + case template.URL: + return string(s), nil + case template.JS: + return string(s), nil + case template.CSS: + return string(s), nil + case template.HTMLAttr: + return string(s), nil + case nil: + return "", nil + case fmt.Stringer: + return s.String(), nil + case error: + return s.Error(), nil + default: + return "", fmt.Errorf("unable to cast %#v of type %T to string", i, i) + } +} + +// ToStringMapStringE casts an interface to a map[string]string type. +func ToStringMapStringE(i interface{}) (map[string]string, error) { + var m = map[string]string{} + + switch v := i.(type) { + case map[string]string: + return v, nil + case map[string]interface{}: + for k, val := range v { + m[ToString(k)] = ToString(val) + } + return m, nil + case map[interface{}]string: + for k, val := range v { + m[ToString(k)] = ToString(val) + } + return m, nil + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToString(val) + } + return m, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + default: + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]string", i, i) + } +} + +// ToStringMapStringSliceE casts an interface to a map[string][]string type. +func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { + var m = map[string][]string{} + + switch v := i.(type) { + case map[string][]string: + return v, nil + case map[string][]interface{}: + for k, val := range v { + m[ToString(k)] = ToStringSlice(val) + } + return m, nil + case map[string]string: + for k, val := range v { + m[ToString(k)] = []string{val} + } + case map[string]interface{}: + for k, val := range v { + switch vt := val.(type) { + case []interface{}: + m[ToString(k)] = ToStringSlice(vt) + case []string: + m[ToString(k)] = vt + default: + m[ToString(k)] = []string{ToString(val)} + } + } + return m, nil + case map[interface{}][]string: + for k, val := range v { + m[ToString(k)] = ToStringSlice(val) + } + return m, nil + case map[interface{}]string: + for k, val := range v { + m[ToString(k)] = ToStringSlice(val) + } + return m, nil + case map[interface{}][]interface{}: + for k, val := range v { + m[ToString(k)] = ToStringSlice(val) + } + return m, nil + case map[interface{}]interface{}: + for k, val := range v { + key, err := ToStringE(k) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) + } + value, err := ToStringSliceE(val) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) + } + m[key] = value + } + case string: + err := jsonStringToObject(v, &m) + return m, err + default: + return m, fmt.Errorf("unable to cast %#v of type %T to map[string][]string", i, i) + } + return m, nil +} + +// ToStringMapBoolE casts an interface to a map[string]bool type. +func ToStringMapBoolE(i interface{}) (map[string]bool, error) { + var m = map[string]bool{} + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToBool(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[ToString(k)] = ToBool(val) + } + return m, nil + case map[string]bool: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + default: + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]bool", i, i) + } +} + +// ToStringMapE casts an interface to a map[string]interface{} type. +func ToStringMapE(i interface{}) (map[string]interface{}, error) { + var m = map[string]interface{}{} + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = val + } + return m, nil + case map[string]interface{}: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + default: + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]interface{}", i, i) + } +} + +// ToStringMapIntE casts an interface to a map[string]int{} type. +func ToStringMapIntE(i interface{}) (map[string]int, error) { + var m = map[string]int{} + if i == nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToInt(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[k] = ToInt(val) + } + return m, nil + case map[string]int: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + } + + if reflect.TypeOf(i).Kind() != reflect.Map { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + + mVal := reflect.ValueOf(m) + v := reflect.ValueOf(i) + for _, keyVal := range v.MapKeys() { + val, err := ToIntE(v.MapIndex(keyVal).Interface()) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i) + } + mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) + } + return m, nil +} + +// ToStringMapInt64E casts an interface to a map[string]int64{} type. +func ToStringMapInt64E(i interface{}) (map[string]int64, error) { + var m = map[string]int64{} + if i == nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + + switch v := i.(type) { + case map[interface{}]interface{}: + for k, val := range v { + m[ToString(k)] = ToInt64(val) + } + return m, nil + case map[string]interface{}: + for k, val := range v { + m[k] = ToInt64(val) + } + return m, nil + case map[string]int64: + return v, nil + case string: + err := jsonStringToObject(v, &m) + return m, err + } + + if reflect.TypeOf(i).Kind() != reflect.Map { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + mVal := reflect.ValueOf(m) + v := reflect.ValueOf(i) + for _, keyVal := range v.MapKeys() { + val, err := ToInt64E(v.MapIndex(keyVal).Interface()) + if err != nil { + return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i) + } + mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) + } + return m, nil +} + +// ToSliceE casts an interface to a []interface{} type. +func ToSliceE(i interface{}) ([]interface{}, error) { + var s []interface{} + + switch v := i.(type) { + case []interface{}: + return append(s, v...), nil + case []map[string]interface{}: + for _, u := range v { + s = append(s, u) + } + return s, nil + default: + return s, fmt.Errorf("unable to cast %#v of type %T to []interface{}", i, i) + } +} + +// ToBoolSliceE casts an interface to a []bool type. +func ToBoolSliceE(i interface{}) ([]bool, error) { + if i == nil { + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } + + switch v := i.(type) { + case []bool: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]bool, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToBoolE(s.Index(j).Interface()) + if err != nil { + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } + a[j] = val + } + return a, nil + default: + return []bool{}, fmt.Errorf("unable to cast %#v of type %T to []bool", i, i) + } +} + +// ToStringSliceE casts an interface to a []string type. +func ToStringSliceE(i interface{}) ([]string, error) { + var a []string + + switch v := i.(type) { + case []interface{}: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []string: + return v, nil + case string: + return strings.Fields(v), nil + case interface{}: + str, err := ToStringE(v) + if err != nil { + return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) + } + return []string{str}, nil + default: + return a, fmt.Errorf("unable to cast %#v of type %T to []string", i, i) + } +} + +// ToIntSliceE casts an interface to a []int type. +func ToIntSliceE(i interface{}) ([]int, error) { + if i == nil { + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) + } + + switch v := i.(type) { + case []int: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]int, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToIntE(s.Index(j).Interface()) + if err != nil { + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) + } + a[j] = val + } + return a, nil + default: + return []int{}, fmt.Errorf("unable to cast %#v of type %T to []int", i, i) + } +} + +// ToDurationSliceE casts an interface to a []time.Duration type. +func ToDurationSliceE(i interface{}) ([]time.Duration, error) { + if i == nil { + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } + + switch v := i.(type) { + case []time.Duration: + return v, nil + } + + kind := reflect.TypeOf(i).Kind() + switch kind { + case reflect.Slice, reflect.Array: + s := reflect.ValueOf(i) + a := make([]time.Duration, s.Len()) + for j := 0; j < s.Len(); j++ { + val, err := ToDurationE(s.Index(j).Interface()) + if err != nil { + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } + a[j] = val + } + return a, nil + default: + return []time.Duration{}, fmt.Errorf("unable to cast %#v of type %T to []time.Duration", i, i) + } +} + +// StringToDate attempts to parse a string into a time.Time type using a +// predefined list of formats. If no suitable format is found, an error is +// returned. +func StringToDate(s string) (time.Time, error) { + return parseDateWith(s, []string{ + time.RFC3339, + "2006-01-02T15:04:05", // iso8601 without timezone + time.RFC1123Z, + time.RFC1123, + time.RFC822Z, + time.RFC822, + time.RFC850, + time.ANSIC, + time.UnixDate, + time.RubyDate, + "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String() + "2006-01-02", + "02 Jan 2006", + "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon + "2006-01-02 15:04:05 -07:00", + "2006-01-02 15:04:05 -0700", + "2006-01-02 15:04:05Z07:00", // RFC3339 without T + "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon + "2006-01-02 15:04:05", + time.Kitchen, + time.Stamp, + time.StampMilli, + time.StampMicro, + time.StampNano, + }) +} + +func parseDateWith(s string, dates []string) (d time.Time, e error) { + for _, dateType := range dates { + if d, e = time.Parse(dateType, s); e == nil { + return + } + } + return d, fmt.Errorf("unable to parse date: %s", s) +} + +// jsonStringToObject attempts to unmarshall a string as JSON into +// the object passed as pointer. +func jsonStringToObject(s string, v interface{}) error { + data := []byte(s) + return json.Unmarshal(data, v) +} diff --git a/vendor/github.com/spf13/cast/indirect.go b/vendor/github.com/spf13/cast/indirect.go deleted file mode 100644 index 093345f737..0000000000 --- a/vendor/github.com/spf13/cast/indirect.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright © 2014 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package cast - -import ( - "reflect" -) - -// From html/template/content.go -// Copyright 2011 The Go Authors. All rights reserved. -// indirect returns the value, after dereferencing as many times -// as necessary to reach the base type (or nil). -func indirect(i any) (any, bool) { - if i == nil { - return nil, false - } - - if t := reflect.TypeOf(i); t.Kind() != reflect.Ptr { - // Avoid creating a reflect.Value if it's not a pointer. - return i, false - } - - v := reflect.ValueOf(i) - - for v.Kind() == reflect.Ptr || (v.Kind() == reflect.Interface && v.Elem().Kind() == reflect.Ptr) { - if v.IsNil() { - return nil, true - } - - v = v.Elem() - } - - return v.Interface(), true -} diff --git a/vendor/github.com/spf13/cast/internal/time.go b/vendor/github.com/spf13/cast/internal/time.go deleted file mode 100644 index 906e9aece3..0000000000 --- a/vendor/github.com/spf13/cast/internal/time.go +++ /dev/null @@ -1,79 +0,0 @@ -package internal - -import ( - "fmt" - "time" -) - -//go:generate stringer -type=TimeFormatType - -type TimeFormatType int - -const ( - TimeFormatNoTimezone TimeFormatType = iota - TimeFormatNamedTimezone - TimeFormatNumericTimezone - TimeFormatNumericAndNamedTimezone - TimeFormatTimeOnly -) - -type TimeFormat struct { - Format string - Typ TimeFormatType -} - -func (f TimeFormat) HasTimezone() bool { - // We don't include the formats with only named timezones, see - // https://github.com/golang/go/issues/19694#issuecomment-289103522 - return f.Typ >= TimeFormatNumericTimezone && f.Typ <= TimeFormatNumericAndNamedTimezone -} - -var TimeFormats = []TimeFormat{ - // Keep common formats at the top. - {"2006-01-02", TimeFormatNoTimezone}, - {time.RFC3339, TimeFormatNumericTimezone}, - {"2006-01-02T15:04:05", TimeFormatNoTimezone}, // iso8601 without timezone - {time.RFC1123Z, TimeFormatNumericTimezone}, - {time.RFC1123, TimeFormatNamedTimezone}, - {time.RFC822Z, TimeFormatNumericTimezone}, - {time.RFC822, TimeFormatNamedTimezone}, - {time.RFC850, TimeFormatNamedTimezone}, - {"2006-01-02 15:04:05.999999999 -0700 MST", TimeFormatNumericAndNamedTimezone}, // Time.String() - {"2006-01-02T15:04:05-0700", TimeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon - {"2006-01-02 15:04:05Z0700", TimeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon - {"2006-01-02 15:04:05", TimeFormatNoTimezone}, - {time.ANSIC, TimeFormatNoTimezone}, - {time.UnixDate, TimeFormatNamedTimezone}, - {time.RubyDate, TimeFormatNumericTimezone}, - {"2006-01-02 15:04:05Z07:00", TimeFormatNumericTimezone}, - {"02 Jan 2006", TimeFormatNoTimezone}, - {"2006-01-02 15:04:05 -07:00", TimeFormatNumericTimezone}, - {"2006-01-02 15:04:05 -0700", TimeFormatNumericTimezone}, - {time.Kitchen, TimeFormatTimeOnly}, - {time.Stamp, TimeFormatTimeOnly}, - {time.StampMilli, TimeFormatTimeOnly}, - {time.StampMicro, TimeFormatTimeOnly}, - {time.StampNano, TimeFormatTimeOnly}, -} - -func ParseDateWith(s string, location *time.Location, formats []TimeFormat) (d time.Time, e error) { - for _, format := range formats { - if d, e = time.Parse(format.Format, s); e == nil { - - // Some time formats have a zone name, but no offset, so it gets - // put in that zone name (not the default one passed in to us), but - // without that zone's offset. So set the location manually. - if format.Typ <= TimeFormatNamedTimezone { - if location == nil { - location = time.Local - } - year, month, day := d.Date() - hour, min, sec := d.Clock() - d = time.Date(year, month, day, hour, min, sec, d.Nanosecond(), location) - } - - return - } - } - return d, fmt.Errorf("unable to parse date: %s", s) -} diff --git a/vendor/github.com/spf13/cast/internal/timeformattype_string.go b/vendor/github.com/spf13/cast/internal/timeformattype_string.go deleted file mode 100644 index 60a29a862b..0000000000 --- a/vendor/github.com/spf13/cast/internal/timeformattype_string.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by "stringer -type=TimeFormatType"; DO NOT EDIT. - -package internal - -import "strconv" - -func _() { - // An "invalid array index" compiler error signifies that the constant values have changed. - // Re-run the stringer command to generate them again. - var x [1]struct{} - _ = x[TimeFormatNoTimezone-0] - _ = x[TimeFormatNamedTimezone-1] - _ = x[TimeFormatNumericTimezone-2] - _ = x[TimeFormatNumericAndNamedTimezone-3] - _ = x[TimeFormatTimeOnly-4] -} - -const _TimeFormatType_name = "TimeFormatNoTimezoneTimeFormatNamedTimezoneTimeFormatNumericTimezoneTimeFormatNumericAndNamedTimezoneTimeFormatTimeOnly" - -var _TimeFormatType_index = [...]uint8{0, 20, 43, 68, 101, 119} - -func (i TimeFormatType) String() string { - if i < 0 || i >= TimeFormatType(len(_TimeFormatType_index)-1) { - return "TimeFormatType(" + strconv.FormatInt(int64(i), 10) + ")" - } - return _TimeFormatType_name[_TimeFormatType_index[i]:_TimeFormatType_index[i+1]] -} diff --git a/vendor/github.com/spf13/cast/map.go b/vendor/github.com/spf13/cast/map.go deleted file mode 100644 index 7d6beb56cc..0000000000 --- a/vendor/github.com/spf13/cast/map.go +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright © 2014 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package cast - -import ( - "encoding/json" - "fmt" - "reflect" -) - -func toMapE[K comparable, V any](i any, keyFn func(any) K, valFn func(any) V) (map[K]V, error) { - m := map[K]V{} - - if i == nil { - return nil, fmt.Errorf(errorMsg, i, i, m) - } - - switch v := i.(type) { - case map[K]V: - return v, nil - - case map[K]any: - for k, val := range v { - m[k] = valFn(val) - } - - return m, nil - - case map[any]V: - for k, val := range v { - m[keyFn(k)] = val - } - - return m, nil - - case map[any]any: - for k, val := range v { - m[keyFn(k)] = valFn(val) - } - - return m, nil - - case string: - err := jsonStringToObject(v, &m) - if err != nil { - return nil, err - } - - return m, nil - - default: - return nil, fmt.Errorf(errorMsg, i, i, m) - } -} - -func toStringMapE[T any](i any, fn func(any) T) (map[string]T, error) { - return toMapE(i, ToString, fn) -} - -// ToStringMapStringE casts any value to a map[string]string type. -func ToStringMapStringE(i any) (map[string]string, error) { - return toStringMapE(i, ToString) -} - -// ToStringMapStringSliceE casts any value to a map[string][]string type. -func ToStringMapStringSliceE(i any) (map[string][]string, error) { - m := map[string][]string{} - - switch v := i.(type) { - case map[string][]string: - return v, nil - case map[string][]any: - for k, val := range v { - m[ToString(k)] = ToStringSlice(val) - } - return m, nil - case map[string]string: - for k, val := range v { - m[ToString(k)] = []string{val} - } - case map[string]any: - for k, val := range v { - switch vt := val.(type) { - case []any: - m[ToString(k)] = ToStringSlice(vt) - case []string: - m[ToString(k)] = vt - default: - m[ToString(k)] = []string{ToString(val)} - } - } - return m, nil - case map[any][]string: - for k, val := range v { - m[ToString(k)] = ToStringSlice(val) - } - return m, nil - case map[any]string: - for k, val := range v { - m[ToString(k)] = ToStringSlice(val) - } - return m, nil - case map[any][]any: - for k, val := range v { - m[ToString(k)] = ToStringSlice(val) - } - return m, nil - case map[any]any: - for k, val := range v { - key, err := ToStringE(k) - if err != nil { - return nil, fmt.Errorf(errorMsg, i, i, m) - } - value, err := ToStringSliceE(val) - if err != nil { - return nil, fmt.Errorf(errorMsg, i, i, m) - } - m[key] = value - } - case string: - err := jsonStringToObject(v, &m) - if err != nil { - return nil, err - } - - return m, nil - default: - return nil, fmt.Errorf(errorMsg, i, i, m) - } - - return m, nil -} - -// ToStringMapBoolE casts any value to a map[string]bool type. -func ToStringMapBoolE(i any) (map[string]bool, error) { - return toStringMapE(i, ToBool) -} - -// ToStringMapE casts any value to a map[string]any type. -func ToStringMapE(i any) (map[string]any, error) { - fn := func(i any) any { return i } - - return toStringMapE(i, fn) -} - -func toStringMapIntE[T int | int64](i any, fn func(any) T, fnE func(any) (T, error)) (map[string]T, error) { - m := map[string]T{} - - if i == nil { - return nil, fmt.Errorf(errorMsg, i, i, m) - } - - switch v := i.(type) { - case map[string]T: - return v, nil - - case map[string]any: - for k, val := range v { - m[k] = fn(val) - } - - return m, nil - - case map[any]T: - for k, val := range v { - m[ToString(k)] = val - } - - return m, nil - - case map[any]any: - for k, val := range v { - m[ToString(k)] = fn(val) - } - - return m, nil - - case string: - err := jsonStringToObject(v, &m) - if err != nil { - return nil, err - } - - return m, nil - } - - if reflect.TypeOf(i).Kind() != reflect.Map { - return nil, fmt.Errorf(errorMsg, i, i, m) - } - - mVal := reflect.ValueOf(m) - v := reflect.ValueOf(i) - - for _, keyVal := range v.MapKeys() { - val, err := fnE(v.MapIndex(keyVal).Interface()) - if err != nil { - return m, fmt.Errorf(errorMsg, i, i, m) - } - - mVal.SetMapIndex(keyVal, reflect.ValueOf(val)) - } - - return m, nil -} - -// ToStringMapIntE casts any value to a map[string]int type. -func ToStringMapIntE(i any) (map[string]int, error) { - return toStringMapIntE(i, ToInt, ToIntE) -} - -// ToStringMapInt64E casts any value to a map[string]int64 type. -func ToStringMapInt64E(i any) (map[string]int64, error) { - return toStringMapIntE(i, ToInt64, ToInt64E) -} - -// jsonStringToObject attempts to unmarshall a string as JSON into -// the object passed as pointer. -func jsonStringToObject(s string, v any) error { - data := []byte(s) - return json.Unmarshal(data, v) -} diff --git a/vendor/github.com/spf13/cast/number.go b/vendor/github.com/spf13/cast/number.go deleted file mode 100644 index a58dc4d1ed..0000000000 --- a/vendor/github.com/spf13/cast/number.go +++ /dev/null @@ -1,549 +0,0 @@ -// Copyright © 2014 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package cast - -import ( - "encoding/json" - "errors" - "fmt" - "regexp" - "strconv" - "strings" - "time" -) - -var errNegativeNotAllowed = errors.New("unable to cast negative value") - -type float64EProvider interface { - Float64() (float64, error) -} - -type float64Provider interface { - Float64() float64 -} - -// Number is a type parameter constraint for functions accepting number types. -// -// It represents the supported number types this package can cast to. -type Number interface { - int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | float32 | float64 -} - -type integer interface { - int | int8 | int16 | int32 | int64 -} - -type unsigned interface { - uint | uint8 | uint16 | uint32 | uint64 -} - -type float interface { - float32 | float64 -} - -// ToNumberE casts any value to a [Number] type. -func ToNumberE[T Number](i any) (T, error) { - var t T - - switch any(t).(type) { - case int: - return toNumberE[T](i, parseNumber[T]) - case int8: - return toNumberE[T](i, parseNumber[T]) - case int16: - return toNumberE[T](i, parseNumber[T]) - case int32: - return toNumberE[T](i, parseNumber[T]) - case int64: - return toNumberE[T](i, parseNumber[T]) - case uint: - return toUnsignedNumberE[T](i, parseNumber[T]) - case uint8: - return toUnsignedNumberE[T](i, parseNumber[T]) - case uint16: - return toUnsignedNumberE[T](i, parseNumber[T]) - case uint32: - return toUnsignedNumberE[T](i, parseNumber[T]) - case uint64: - return toUnsignedNumberE[T](i, parseNumber[T]) - case float32: - return toNumberE[T](i, parseNumber[T]) - case float64: - return toNumberE[T](i, parseNumber[T]) - default: - return 0, fmt.Errorf("unknown number type: %T", t) - } -} - -// ToNumber casts any value to a [Number] type. -func ToNumber[T Number](i any) T { - v, _ := ToNumberE[T](i) - - return v -} - -// toNumber's semantics differ from other "to" functions. -// It returns false as the second parameter if the conversion fails. -// This is to signal other callers that they should proceed with their own conversions. -func toNumber[T Number](i any) (T, bool) { - i, _ = indirect(i) - - switch s := i.(type) { - case T: - return s, true - case int: - return T(s), true - case int8: - return T(s), true - case int16: - return T(s), true - case int32: - return T(s), true - case int64: - return T(s), true - case uint: - return T(s), true - case uint8: - return T(s), true - case uint16: - return T(s), true - case uint32: - return T(s), true - case uint64: - return T(s), true - case float32: - return T(s), true - case float64: - return T(s), true - case bool: - if s { - return 1, true - } - - return 0, true - case nil: - return 0, true - case time.Weekday: - return T(s), true - case time.Month: - return T(s), true - } - - return 0, false -} - -func toNumberE[T Number](i any, parseFn func(string) (T, error)) (T, error) { - n, ok := toNumber[T](i) - if ok { - return n, nil - } - - i, _ = indirect(i) - - switch s := i.(type) { - case string: - if s == "" { - return 0, nil - } - - v, err := parseFn(s) - if err != nil { - return 0, fmt.Errorf(errorMsgWith, i, i, n, err) - } - - return v, nil - case json.Number: - if s == "" { - return 0, nil - } - - v, err := parseFn(string(s)) - if err != nil { - return 0, fmt.Errorf(errorMsgWith, i, i, n, err) - } - - return v, nil - case float64EProvider: - if _, ok := any(n).(float64); !ok { - return 0, fmt.Errorf(errorMsg, i, i, n) - } - - v, err := s.Float64() - if err != nil { - return 0, fmt.Errorf(errorMsg, i, i, n) - } - - return T(v), nil - case float64Provider: - if _, ok := any(n).(float64); !ok { - return 0, fmt.Errorf(errorMsg, i, i, n) - } - - return T(s.Float64()), nil - default: - if i, ok := resolveAlias(i); ok { - return toNumberE(i, parseFn) - } - - return 0, fmt.Errorf(errorMsg, i, i, n) - } -} - -func toUnsignedNumber[T Number](i any) (T, bool, bool) { - i, _ = indirect(i) - - switch s := i.(type) { - case T: - return s, true, true - case int: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - case int8: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - case int16: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - case int32: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - case int64: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - case uint: - return T(s), true, true - case uint8: - return T(s), true, true - case uint16: - return T(s), true, true - case uint32: - return T(s), true, true - case uint64: - return T(s), true, true - case float32: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - case float64: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - case bool: - if s { - return 1, true, true - } - - return 0, true, true - case nil: - return 0, true, true - case time.Weekday: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - case time.Month: - if s < 0 { - return 0, false, false - } - - return T(s), true, true - } - - return 0, true, false -} - -func toUnsignedNumberE[T Number](i any, parseFn func(string) (T, error)) (T, error) { - n, valid, ok := toUnsignedNumber[T](i) - if ok { - return n, nil - } - - i, _ = indirect(i) - - if !valid { - return 0, errNegativeNotAllowed - } - - switch s := i.(type) { - case string: - if s == "" { - return 0, nil - } - - v, err := parseFn(s) - if err != nil { - return 0, fmt.Errorf(errorMsgWith, i, i, n, err) - } - - return v, nil - case json.Number: - if s == "" { - return 0, nil - } - - v, err := parseFn(string(s)) - if err != nil { - return 0, fmt.Errorf(errorMsgWith, i, i, n, err) - } - - return v, nil - case float64EProvider: - if _, ok := any(n).(float64); !ok { - return 0, fmt.Errorf(errorMsg, i, i, n) - } - - v, err := s.Float64() - if err != nil { - return 0, fmt.Errorf(errorMsg, i, i, n) - } - - if v < 0 { - return 0, errNegativeNotAllowed - } - - return T(v), nil - case float64Provider: - if _, ok := any(n).(float64); !ok { - return 0, fmt.Errorf(errorMsg, i, i, n) - } - - v := s.Float64() - - if v < 0 { - return 0, errNegativeNotAllowed - } - - return T(v), nil - default: - if i, ok := resolveAlias(i); ok { - return toUnsignedNumberE(i, parseFn) - } - - return 0, fmt.Errorf(errorMsg, i, i, n) - } -} - -func parseNumber[T Number](s string) (T, error) { - var t T - - switch any(t).(type) { - case int: - v, err := parseInt[int](s) - - return T(v), err - case int8: - v, err := parseInt[int8](s) - - return T(v), err - case int16: - v, err := parseInt[int16](s) - - return T(v), err - case int32: - v, err := parseInt[int32](s) - - return T(v), err - case int64: - v, err := parseInt[int64](s) - - return T(v), err - case uint: - v, err := parseUint[uint](s) - - return T(v), err - case uint8: - v, err := parseUint[uint8](s) - - return T(v), err - case uint16: - v, err := parseUint[uint16](s) - - return T(v), err - case uint32: - v, err := parseUint[uint32](s) - - return T(v), err - case uint64: - v, err := parseUint[uint64](s) - - return T(v), err - case float32: - v, err := strconv.ParseFloat(s, 32) - - return T(v), err - case float64: - v, err := strconv.ParseFloat(s, 64) - - return T(v), err - - default: - return 0, fmt.Errorf("unknown number type: %T", t) - } -} - -func parseInt[T integer](s string) (T, error) { - v, err := strconv.ParseInt(trimDecimal(s), 0, 0) - if err != nil { - return 0, err - } - - return T(v), nil -} - -func parseUint[T unsigned](s string) (T, error) { - v, err := strconv.ParseUint(strings.TrimLeft(trimDecimal(s), "+"), 0, 0) - if err != nil { - return 0, err - } - - return T(v), nil -} - -func parseFloat[T float](s string) (T, error) { - var t T - - var v any - var err error - - switch any(t).(type) { - case float32: - n, e := strconv.ParseFloat(s, 32) - - v = float32(n) - err = e - case float64: - n, e := strconv.ParseFloat(s, 64) - - v = float64(n) - err = e - } - - return v.(T), err -} - -// ToFloat64E casts an interface to a float64 type. -func ToFloat64E(i any) (float64, error) { - return toNumberE[float64](i, parseFloat[float64]) -} - -// ToFloat32E casts an interface to a float32 type. -func ToFloat32E(i any) (float32, error) { - return toNumberE[float32](i, parseFloat[float32]) -} - -// ToInt64E casts an interface to an int64 type. -func ToInt64E(i any) (int64, error) { - return toNumberE[int64](i, parseInt[int64]) -} - -// ToInt32E casts an interface to an int32 type. -func ToInt32E(i any) (int32, error) { - return toNumberE[int32](i, parseInt[int32]) -} - -// ToInt16E casts an interface to an int16 type. -func ToInt16E(i any) (int16, error) { - return toNumberE[int16](i, parseInt[int16]) -} - -// ToInt8E casts an interface to an int8 type. -func ToInt8E(i any) (int8, error) { - return toNumberE[int8](i, parseInt[int8]) -} - -// ToIntE casts an interface to an int type. -func ToIntE(i any) (int, error) { - return toNumberE[int](i, parseInt[int]) -} - -// ToUintE casts an interface to a uint type. -func ToUintE(i any) (uint, error) { - return toUnsignedNumberE[uint](i, parseUint[uint]) -} - -// ToUint64E casts an interface to a uint64 type. -func ToUint64E(i any) (uint64, error) { - return toUnsignedNumberE[uint64](i, parseUint[uint64]) -} - -// ToUint32E casts an interface to a uint32 type. -func ToUint32E(i any) (uint32, error) { - return toUnsignedNumberE[uint32](i, parseUint[uint32]) -} - -// ToUint16E casts an interface to a uint16 type. -func ToUint16E(i any) (uint16, error) { - return toUnsignedNumberE[uint16](i, parseUint[uint16]) -} - -// ToUint8E casts an interface to a uint type. -func ToUint8E(i any) (uint8, error) { - return toUnsignedNumberE[uint8](i, parseUint[uint8]) -} - -func trimZeroDecimal(s string) string { - var foundZero bool - for i := len(s); i > 0; i-- { - switch s[i-1] { - case '.': - if foundZero { - return s[:i-1] - } - case '0': - foundZero = true - default: - return s - } - } - return s -} - -var stringNumberRe = regexp.MustCompile(`^([-+]?\d*)(\.\d*)?$`) - -// see [BenchmarkDecimal] for details about the implementation -func trimDecimal(s string) string { - if !strings.Contains(s, ".") { - return s - } - - matches := stringNumberRe.FindStringSubmatch(s) - if matches != nil { - // matches[1] is the captured integer part with sign - s = matches[1] - - // handle special cases - switch s { - case "-", "+": - s += "0" - case "": - s = "0" - } - - return s - } - - return s -} diff --git a/vendor/github.com/spf13/cast/slice.go b/vendor/github.com/spf13/cast/slice.go deleted file mode 100644 index e6a8328c60..0000000000 --- a/vendor/github.com/spf13/cast/slice.go +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright © 2014 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package cast - -import ( - "fmt" - "reflect" - "strings" -) - -// ToSliceE casts any value to a []any type. -func ToSliceE(i any) ([]any, error) { - i, _ = indirect(i) - - var s []any - - switch v := i.(type) { - case []any: - // TODO: use slices.Clone - return append(s, v...), nil - case []map[string]any: - for _, u := range v { - s = append(s, u) - } - - return s, nil - default: - return s, fmt.Errorf(errorMsg, i, i, s) - } -} - -func toSliceE[T Basic](i any) ([]T, error) { - v, ok, err := toSliceEOk[T](i) - if err != nil { - return nil, err - } - - if !ok { - return nil, fmt.Errorf(errorMsg, i, i, []T{}) - } - - return v, nil -} - -func toSliceEOk[T Basic](i any) ([]T, bool, error) { - i, _ = indirect(i) - if i == nil { - return nil, true, fmt.Errorf(errorMsg, i, i, []T{}) - } - - switch v := i.(type) { - case []T: - // TODO: clone slice - return v, true, nil - } - - kind := reflect.TypeOf(i).Kind() - switch kind { - case reflect.Slice, reflect.Array: - s := reflect.ValueOf(i) - a := make([]T, s.Len()) - - for j := 0; j < s.Len(); j++ { - val, err := ToE[T](s.Index(j).Interface()) - if err != nil { - return nil, true, fmt.Errorf(errorMsg, i, i, []T{}) - } - - a[j] = val - } - - return a, true, nil - default: - return nil, false, nil - } -} - -// ToStringSliceE casts any value to a []string type. -func ToStringSliceE(i any) ([]string, error) { - if a, ok, err := toSliceEOk[string](i); ok { - if err != nil { - return nil, err - } - - return a, nil - } - - var a []string - - switch v := i.(type) { - case string: - return strings.Fields(v), nil - case any: - str, err := ToStringE(v) - if err != nil { - return nil, fmt.Errorf(errorMsg, i, i, a) - } - - return []string{str}, nil - default: - return nil, fmt.Errorf(errorMsg, i, i, a) - } -} diff --git a/vendor/github.com/spf13/cast/time.go b/vendor/github.com/spf13/cast/time.go deleted file mode 100644 index 744cd5accd..0000000000 --- a/vendor/github.com/spf13/cast/time.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright © 2014 Steve Francia . -// -// Use of this source code is governed by an MIT-style -// license that can be found in the LICENSE file. - -package cast - -import ( - "encoding/json" - "errors" - "fmt" - "strings" - "time" - - "github.com/spf13/cast/internal" -) - -// ToTimeE any value to a [time.Time] type. -func ToTimeE(i any) (time.Time, error) { - return ToTimeInDefaultLocationE(i, time.UTC) -} - -// ToTimeInDefaultLocationE casts an empty interface to [time.Time], -// interpreting inputs without a timezone to be in the given location, -// or the local timezone if nil. -func ToTimeInDefaultLocationE(i any, location *time.Location) (tim time.Time, err error) { - i, _ = indirect(i) - - switch v := i.(type) { - case time.Time: - return v, nil - case string: - return StringToDateInDefaultLocation(v, location) - case json.Number: - // Originally this used ToInt64E, but adding string float conversion broke ToTime. - // the behavior of ToTime would have changed if we continued using it. - // For now, using json.Number's own Int64 method should be good enough to preserve backwards compatibility. - v = json.Number(trimZeroDecimal(string(v))) - s, err1 := v.Int64() - if err1 != nil { - return time.Time{}, fmt.Errorf(errorMsg, i, i, time.Time{}) - } - return time.Unix(s, 0), nil - case int: - return time.Unix(int64(v), 0), nil - case int32: - return time.Unix(int64(v), 0), nil - case int64: - return time.Unix(v, 0), nil - case uint: - return time.Unix(int64(v), 0), nil - case uint32: - return time.Unix(int64(v), 0), nil - case uint64: - return time.Unix(int64(v), 0), nil - case nil: - return time.Time{}, nil - default: - return time.Time{}, fmt.Errorf(errorMsg, i, i, time.Time{}) - } -} - -// ToDurationE casts any value to a [time.Duration] type. -func ToDurationE(i any) (time.Duration, error) { - i, _ = indirect(i) - - switch s := i.(type) { - case time.Duration: - return s, nil - case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: - v, err := ToInt64E(s) - if err != nil { - // TODO: once there is better error handling, this should be easier - return 0, errors.New(strings.ReplaceAll(err.Error(), " int64", "time.Duration")) - } - - return time.Duration(v), nil - case float32, float64, float64EProvider, float64Provider: - v, err := ToFloat64E(s) - if err != nil { - // TODO: once there is better error handling, this should be easier - return 0, errors.New(strings.ReplaceAll(err.Error(), " float64", "time.Duration")) - } - - return time.Duration(v), nil - case string: - if !strings.ContainsAny(s, "nsuµmh") { - return time.ParseDuration(s + "ns") - } - - return time.ParseDuration(s) - case nil: - return time.Duration(0), nil - default: - if i, ok := resolveAlias(i); ok { - return ToDurationE(i) - } - - return 0, fmt.Errorf(errorMsg, i, i, time.Duration(0)) - } -} - -// StringToDate attempts to parse a string into a [time.Time] type using a -// predefined list of formats. -// -// If no suitable format is found, an error is returned. -func StringToDate(s string) (time.Time, error) { - return internal.ParseDateWith(s, time.UTC, internal.TimeFormats) -} - -// StringToDateInDefaultLocation casts an empty interface to a [time.Time], -// interpreting inputs without a timezone to be in the given location, -// or the local timezone if nil. -func StringToDateInDefaultLocation(s string, location *time.Location) (time.Time, error) { - return internal.ParseDateWith(s, location, internal.TimeFormats) -} diff --git a/vendor/github.com/spf13/cast/zz_generated.go b/vendor/github.com/spf13/cast/zz_generated.go deleted file mode 100644 index ce3ec0f78f..0000000000 --- a/vendor/github.com/spf13/cast/zz_generated.go +++ /dev/null @@ -1,261 +0,0 @@ -// Code generated by cast generator. DO NOT EDIT. - -package cast - -import "time" - -// ToBool casts any value to a(n) bool type. -func ToBool(i any) bool { - v, _ := ToBoolE(i) - return v -} - -// ToString casts any value to a(n) string type. -func ToString(i any) string { - v, _ := ToStringE(i) - return v -} - -// ToTime casts any value to a(n) time.Time type. -func ToTime(i any) time.Time { - v, _ := ToTimeE(i) - return v -} - -// ToTimeInDefaultLocation casts any value to a(n) time.Time type. -func ToTimeInDefaultLocation(i any, location *time.Location) time.Time { - v, _ := ToTimeInDefaultLocationE(i, location) - return v -} - -// ToDuration casts any value to a(n) time.Duration type. -func ToDuration(i any) time.Duration { - v, _ := ToDurationE(i) - return v -} - -// ToInt casts any value to a(n) int type. -func ToInt(i any) int { - v, _ := ToIntE(i) - return v -} - -// ToInt8 casts any value to a(n) int8 type. -func ToInt8(i any) int8 { - v, _ := ToInt8E(i) - return v -} - -// ToInt16 casts any value to a(n) int16 type. -func ToInt16(i any) int16 { - v, _ := ToInt16E(i) - return v -} - -// ToInt32 casts any value to a(n) int32 type. -func ToInt32(i any) int32 { - v, _ := ToInt32E(i) - return v -} - -// ToInt64 casts any value to a(n) int64 type. -func ToInt64(i any) int64 { - v, _ := ToInt64E(i) - return v -} - -// ToUint casts any value to a(n) uint type. -func ToUint(i any) uint { - v, _ := ToUintE(i) - return v -} - -// ToUint8 casts any value to a(n) uint8 type. -func ToUint8(i any) uint8 { - v, _ := ToUint8E(i) - return v -} - -// ToUint16 casts any value to a(n) uint16 type. -func ToUint16(i any) uint16 { - v, _ := ToUint16E(i) - return v -} - -// ToUint32 casts any value to a(n) uint32 type. -func ToUint32(i any) uint32 { - v, _ := ToUint32E(i) - return v -} - -// ToUint64 casts any value to a(n) uint64 type. -func ToUint64(i any) uint64 { - v, _ := ToUint64E(i) - return v -} - -// ToFloat32 casts any value to a(n) float32 type. -func ToFloat32(i any) float32 { - v, _ := ToFloat32E(i) - return v -} - -// ToFloat64 casts any value to a(n) float64 type. -func ToFloat64(i any) float64 { - v, _ := ToFloat64E(i) - return v -} - -// ToStringMapString casts any value to a(n) map[string]string type. -func ToStringMapString(i any) map[string]string { - v, _ := ToStringMapStringE(i) - return v -} - -// ToStringMapStringSlice casts any value to a(n) map[string][]string type. -func ToStringMapStringSlice(i any) map[string][]string { - v, _ := ToStringMapStringSliceE(i) - return v -} - -// ToStringMapBool casts any value to a(n) map[string]bool type. -func ToStringMapBool(i any) map[string]bool { - v, _ := ToStringMapBoolE(i) - return v -} - -// ToStringMapInt casts any value to a(n) map[string]int type. -func ToStringMapInt(i any) map[string]int { - v, _ := ToStringMapIntE(i) - return v -} - -// ToStringMapInt64 casts any value to a(n) map[string]int64 type. -func ToStringMapInt64(i any) map[string]int64 { - v, _ := ToStringMapInt64E(i) - return v -} - -// ToStringMap casts any value to a(n) map[string]any type. -func ToStringMap(i any) map[string]any { - v, _ := ToStringMapE(i) - return v -} - -// ToSlice casts any value to a(n) []any type. -func ToSlice(i any) []any { - v, _ := ToSliceE(i) - return v -} - -// ToBoolSlice casts any value to a(n) []bool type. -func ToBoolSlice(i any) []bool { - v, _ := ToBoolSliceE(i) - return v -} - -// ToStringSlice casts any value to a(n) []string type. -func ToStringSlice(i any) []string { - v, _ := ToStringSliceE(i) - return v -} - -// ToIntSlice casts any value to a(n) []int type. -func ToIntSlice(i any) []int { - v, _ := ToIntSliceE(i) - return v -} - -// ToInt64Slice casts any value to a(n) []int64 type. -func ToInt64Slice(i any) []int64 { - v, _ := ToInt64SliceE(i) - return v -} - -// ToUintSlice casts any value to a(n) []uint type. -func ToUintSlice(i any) []uint { - v, _ := ToUintSliceE(i) - return v -} - -// ToFloat64Slice casts any value to a(n) []float64 type. -func ToFloat64Slice(i any) []float64 { - v, _ := ToFloat64SliceE(i) - return v -} - -// ToDurationSlice casts any value to a(n) []time.Duration type. -func ToDurationSlice(i any) []time.Duration { - v, _ := ToDurationSliceE(i) - return v -} - -// ToBoolSliceE casts any value to a(n) []bool type. -func ToBoolSliceE(i any) ([]bool, error) { - return toSliceE[bool](i) -} - -// ToDurationSliceE casts any value to a(n) []time.Duration type. -func ToDurationSliceE(i any) ([]time.Duration, error) { - return toSliceE[time.Duration](i) -} - -// ToIntSliceE casts any value to a(n) []int type. -func ToIntSliceE(i any) ([]int, error) { - return toSliceE[int](i) -} - -// ToInt8SliceE casts any value to a(n) []int8 type. -func ToInt8SliceE(i any) ([]int8, error) { - return toSliceE[int8](i) -} - -// ToInt16SliceE casts any value to a(n) []int16 type. -func ToInt16SliceE(i any) ([]int16, error) { - return toSliceE[int16](i) -} - -// ToInt32SliceE casts any value to a(n) []int32 type. -func ToInt32SliceE(i any) ([]int32, error) { - return toSliceE[int32](i) -} - -// ToInt64SliceE casts any value to a(n) []int64 type. -func ToInt64SliceE(i any) ([]int64, error) { - return toSliceE[int64](i) -} - -// ToUintSliceE casts any value to a(n) []uint type. -func ToUintSliceE(i any) ([]uint, error) { - return toSliceE[uint](i) -} - -// ToUint8SliceE casts any value to a(n) []uint8 type. -func ToUint8SliceE(i any) ([]uint8, error) { - return toSliceE[uint8](i) -} - -// ToUint16SliceE casts any value to a(n) []uint16 type. -func ToUint16SliceE(i any) ([]uint16, error) { - return toSliceE[uint16](i) -} - -// ToUint32SliceE casts any value to a(n) []uint32 type. -func ToUint32SliceE(i any) ([]uint32, error) { - return toSliceE[uint32](i) -} - -// ToUint64SliceE casts any value to a(n) []uint64 type. -func ToUint64SliceE(i any) ([]uint64, error) { - return toSliceE[uint64](i) -} - -// ToFloat32SliceE casts any value to a(n) []float32 type. -func ToFloat32SliceE(i any) ([]float32, error) { - return toSliceE[float32](i) -} - -// ToFloat64SliceE casts any value to a(n) []float64 type. -func ToFloat64SliceE(i any) ([]float64, error) { - return toSliceE[float64](i) -} diff --git a/vendor/github.com/trivago/tgo/LICENSE b/vendor/github.com/trivago/tgo/LICENSE new file mode 100644 index 0000000000..8f71f43fee --- /dev/null +++ b/vendor/github.com/trivago/tgo/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/vendor/github.com/trivago/tgo/tcontainer/arrays.go b/vendor/github.com/trivago/tgo/tcontainer/arrays.go new file mode 100644 index 0000000000..ede9aed3ed --- /dev/null +++ b/vendor/github.com/trivago/tgo/tcontainer/arrays.go @@ -0,0 +1,113 @@ +// Copyright 2015-2018 trivago N.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcontainer + +import "sort" + +// Int64Slice is a typedef to allow sortable int64 slices +type Int64Slice []int64 + +func (s Int64Slice) Len() int { + return len(s) +} + +func (s Int64Slice) Less(i, j int) bool { + return s[i] < s[j] +} + +func (s Int64Slice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// Sort is a shortcut for sort.Sort(s) +func (s Int64Slice) Sort() { + sort.Sort(s) +} + +// IsSorted is a shortcut for sort.IsSorted(s) +func (s Int64Slice) IsSorted() bool { + return sort.IsSorted(s) +} + +// Set sets all values in this slice to the given value +func (s Int64Slice) Set(v int64) { + for i := range s { + s[i] = v + } +} + +// Uint64Slice is a typedef to allow sortable uint64 slices +type Uint64Slice []uint64 + +func (s Uint64Slice) Len() int { + return len(s) +} + +func (s Uint64Slice) Less(i, j int) bool { + return s[i] < s[j] +} + +func (s Uint64Slice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// Sort is a shortcut for sort.Sort(s) +func (s Uint64Slice) Sort() { + sort.Sort(s) +} + +// IsSorted is a shortcut for sort.IsSorted(s) +func (s Uint64Slice) IsSorted() bool { + return sort.IsSorted(s) +} + +// Set sets all values in this slice to the given value +func (s Uint64Slice) Set(v uint64) { + for i := range s { + s[i] = v + } +} + +// Float32Slice is a typedef to allow sortable float32 slices +type Float32Slice []float32 + +func (s Float32Slice) Len() int { + return len(s) +} + +func (s Float32Slice) Less(i, j int) bool { + return s[i] < s[j] +} + +func (s Float32Slice) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +// Sort is a shortcut for sort.Sort(s) +func (s Float32Slice) Sort() { + sort.Sort(s) +} + +// IsSorted is a shortcut for sort.IsSorted(s) +func (s Float32Slice) IsSorted() bool { + return sort.IsSorted(s) +} + +// Set sets all values in this slice to the given value +func (s Float32Slice) Set(v float32) { + for i := range s { + s[i] = v + } +} diff --git a/vendor/github.com/trivago/tgo/tcontainer/bytepool.go b/vendor/github.com/trivago/tgo/tcontainer/bytepool.go new file mode 100644 index 0000000000..c1290b766d --- /dev/null +++ b/vendor/github.com/trivago/tgo/tcontainer/bytepool.go @@ -0,0 +1,157 @@ +// Copyright 2015-2018 trivago N.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcontainer + +import ( + "reflect" + "runtime" + "sync/atomic" + "unsafe" +) + +const ( + tiny = 64 + small = 512 + medium = 1024 + large = 1024 * 10 + huge = 1024 * 100 + + tinyCount = 16384 // 1 MB + smallCount = 2048 // 1 MB + mediumCount = 1024 // 1 MB + largeCount = 102 // ~1 MB + hugeCount = 10 // ~1 MB +) + +type byteSlab struct { + buffer []byte + bufferSize uintptr + stride uintptr + basePtr *uintptr + nextPtr *uintptr +} + +// BytePool is a fragmentation friendly way to allocated byte slices. +type BytePool struct { + tinySlab byteSlab + smallSlab byteSlab + mediumSlab byteSlab + largeSlab byteSlab + hugeSlab byteSlab +} + +func newByteSlab(size, count int) byteSlab { + bufferSize := count * size + buffer := make([]byte, bufferSize) + basePtr := (*reflect.SliceHeader)(unsafe.Pointer(&buffer)).Data + nextPtr := basePtr + uintptr(bufferSize) + + return byteSlab{ + buffer: buffer, + bufferSize: uintptr(bufferSize), + stride: uintptr(size), + basePtr: &basePtr, + nextPtr: &nextPtr, + } +} + +func (slab *byteSlab) getSlice(size int) (chunk []byte) { + chunkHeader := (*reflect.SliceHeader)(unsafe.Pointer(&chunk)) + chunkHeader.Len = size + chunkHeader.Cap = int(slab.stride) + + for { + // WARNING: The following two lines are order sensitive + basePtr := atomic.LoadUintptr(slab.basePtr) + nextPtr := atomic.AddUintptr(slab.nextPtr, -slab.stride) + lastPtr := basePtr + slab.bufferSize + + switch { + case nextPtr < basePtr || nextPtr >= lastPtr: + // out of range either means alloc while realloc or race between + // base and next during realloc. In the latter case we lose a chunk. + runtime.Gosched() + + case nextPtr == basePtr: + // Last item: realloc + slab.buffer = make([]byte, slab.bufferSize) + dataPtr := (*reflect.SliceHeader)(unsafe.Pointer(&slab.buffer)).Data + + // WARNING: The following two lines are order sensitive + atomic.StoreUintptr(slab.nextPtr, dataPtr+slab.bufferSize) + atomic.StoreUintptr(slab.basePtr, dataPtr) + fallthrough + + default: + chunkHeader.Data = nextPtr + return + } + } +} + +// NewBytePool creates a new BytePool with each slab using 1 MB of storage. +// The pool contains 5 slabs of different sizes: 64B, 512B, 1KB, 10KB and 100KB. +// Allocations above 100KB will be allocated directly. +func NewBytePool() BytePool { + return BytePool{ + tinySlab: newByteSlab(tiny, tinyCount), + smallSlab: newByteSlab(small, smallCount), + mediumSlab: newByteSlab(medium, mediumCount), + largeSlab: newByteSlab(large, largeCount), + hugeSlab: newByteSlab(huge, hugeCount), + } +} + +// NewBytePoolWithSize creates a new BytePool with each slab size using n MB of +// storage. See NewBytePool() for slab size details. +func NewBytePoolWithSize(n int) BytePool { + if n <= 0 { + n = 1 + } + return BytePool{ + tinySlab: newByteSlab(tiny, tinyCount*n), + smallSlab: newByteSlab(small, smallCount*n), + mediumSlab: newByteSlab(medium, mediumCount*n), + largeSlab: newByteSlab(large, largeCount*n), + hugeSlab: newByteSlab(huge, hugeCount*n), + } +} + +// Get returns a slice allocated to a normalized size. +// Sizes are organized in evenly sized buckets so that fragmentation is kept low. +func (b *BytePool) Get(size int) []byte { + switch { + case size == 0: + return []byte{} + + case size <= tiny: + return b.tinySlab.getSlice(size) + + case size <= small: + return b.smallSlab.getSlice(size) + + case size <= medium: + return b.mediumSlab.getSlice(size) + + case size <= large: + return b.largeSlab.getSlice(size) + + case size <= huge: + return b.hugeSlab.getSlice(size) + + default: + return make([]byte, size) + } +} diff --git a/vendor/github.com/trivago/tgo/tcontainer/marshalmap.go b/vendor/github.com/trivago/tgo/tcontainer/marshalmap.go new file mode 100644 index 0000000000..7564f3b5f7 --- /dev/null +++ b/vendor/github.com/trivago/tgo/tcontainer/marshalmap.go @@ -0,0 +1,565 @@ +// Copyright 2015-2018 trivago N.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcontainer + +import ( + "fmt" + "reflect" + "strconv" + "strings" + "time" + + "github.com/trivago/tgo/treflect" +) + +// MarshalMap is a wrapper type to attach converter methods to maps normally +// returned by marshalling methods, i.e. key/value parsers. +// All methods that do a conversion will return an error if the value stored +// behind key is not of the expected type or if the key is not existing in the +// map. +type MarshalMap map[string]interface{} + +const ( + // MarshalMapSeparator defines the rune used for path separation + MarshalMapSeparator = '/' + // MarshalMapArrayBegin defines the rune starting array index notation + MarshalMapArrayBegin = '[' + // MarshalMapArrayEnd defines the rune ending array index notation + MarshalMapArrayEnd = ']' +) + +// NewMarshalMap creates a new marshal map (string -> interface{}) +func NewMarshalMap() MarshalMap { + return make(map[string]interface{}) +} + +// TryConvertToMarshalMap converts collections to MarshalMap if possible. +// This is a deep conversion, i.e. each element in the collection will be +// traversed. You can pass a formatKey function that will be applied to all +// string keys that are detected. +func TryConvertToMarshalMap(value interface{}, formatKey func(string) string) interface{} { + valueMeta := reflect.ValueOf(value) + switch valueMeta.Kind() { + default: + return value + + case reflect.Array, reflect.Slice: + arrayLen := valueMeta.Len() + converted := make([]interface{}, arrayLen) + for i := 0; i < arrayLen; i++ { + converted[i] = TryConvertToMarshalMap(valueMeta.Index(i).Interface(), formatKey) + } + return converted + + case reflect.Map: + converted := NewMarshalMap() + keys := valueMeta.MapKeys() + + for _, keyMeta := range keys { + strKey, isString := keyMeta.Interface().(string) + if !isString { + continue + } + if formatKey != nil { + strKey = formatKey(strKey) + } + val := valueMeta.MapIndex(keyMeta).Interface() + converted[strKey] = TryConvertToMarshalMap(val, formatKey) + } + return converted // ### return, converted MarshalMap ### + } +} + +// ConvertToMarshalMap tries to convert a compatible map type to a marshal map. +// Compatible types are map[interface{}]interface{}, map[string]interface{} and of +// course MarshalMap. The same rules as for ConvertValueToMarshalMap apply. +func ConvertToMarshalMap(value interface{}, formatKey func(string) string) (MarshalMap, error) { + converted := TryConvertToMarshalMap(value, formatKey) + if result, isMap := converted.(MarshalMap); isMap { + return result, nil + } + return nil, fmt.Errorf("Root value cannot be converted to MarshalMap") +} + +// Clone creates a copy of the given MarshalMap. +func (mmap MarshalMap) Clone() MarshalMap { + clone := cloneMap(reflect.ValueOf(mmap)) + return clone.Interface().(MarshalMap) +} + +func cloneMap(mapValue reflect.Value) reflect.Value { + clone := reflect.MakeMap(mapValue.Type()) + keys := mapValue.MapKeys() + + for _, k := range keys { + v := mapValue.MapIndex(k) + switch k.Kind() { + default: + clone.SetMapIndex(k, v) + + case reflect.Array, reflect.Slice: + if v.Type().Elem().Kind() == reflect.Map { + sliceCopy := reflect.MakeSlice(v.Type(), v.Len(), v.Len()) + for i := 0; i < v.Len(); i++ { + element := v.Index(i) + sliceCopy.Index(i).Set(cloneMap(element)) + } + } else { + sliceCopy := reflect.MakeSlice(v.Type(), 0, v.Len()) + reflect.Copy(sliceCopy, v) + clone.SetMapIndex(k, sliceCopy) + } + + case reflect.Map: + vClone := cloneMap(v) + clone.SetMapIndex(k, vClone) + } + } + + return clone +} + +// Bool returns a value at key that is expected to be a boolean +func (mmap MarshalMap) Bool(key string) (bool, error) { + val, exists := mmap.Value(key) + if !exists { + return false, fmt.Errorf(`"%s" is not set`, key) + } + + boolValue, isBool := val.(bool) + if !isBool { + return false, fmt.Errorf(`"%s" is expected to be a boolean`, key) + } + return boolValue, nil +} + +// Uint returns a value at key that is expected to be an uint64 or compatible +// integer value. +func (mmap MarshalMap) Uint(key string) (uint64, error) { + val, exists := mmap.Value(key) + if !exists { + return 0, fmt.Errorf(`"%s" is not set`, key) + } + + if intVal, isNumber := treflect.Uint64(val); isNumber { + return intVal, nil + } + + return 0, fmt.Errorf(`"%s" is expected to be an unsigned number type`, key) +} + +// Int returns a value at key that is expected to be an int64 or compatible +// integer value. +func (mmap MarshalMap) Int(key string) (int64, error) { + val, exists := mmap.Value(key) + if !exists { + return 0, fmt.Errorf(`"%s" is not set`, key) + } + + if intVal, isNumber := treflect.Int64(val); isNumber { + return intVal, nil + } + + return 0, fmt.Errorf(`"%s" is expected to be a signed number type`, key) +} + +// Float returns a value at key that is expected to be a float64 or compatible +// float value. +func (mmap MarshalMap) Float(key string) (float64, error) { + val, exists := mmap.Value(key) + if !exists { + return 0, fmt.Errorf(`"%s" is not set`, key) + } + + if floatVal, isNumber := treflect.Float64(val); isNumber { + return floatVal, nil + } + + return 0, fmt.Errorf(`"%s" is expected to be a signed number type`, key) +} + +// Duration returns a value at key that is expected to be a string +func (mmap MarshalMap) Duration(key string) (time.Duration, error) { + val, exists := mmap.Value(key) + if !exists { + return time.Duration(0), fmt.Errorf(`"%s" is not set`, key) + } + + switch val.(type) { + case time.Duration: + return val.(time.Duration), nil + case string: + return time.ParseDuration(val.(string)) + } + + return time.Duration(0), fmt.Errorf(`"%s" is expected to be a duration or string`, key) +} + +// String returns a value at key that is expected to be a string +func (mmap MarshalMap) String(key string) (string, error) { + val, exists := mmap.Value(key) + if !exists { + return "", fmt.Errorf(`"%s" is not set`, key) + } + + strValue, isString := val.(string) + if !isString { + return "", fmt.Errorf(`"%s" is expected to be a string`, key) + } + return strValue, nil +} + +// Bytes returns a value at key that is expected to be a []byte +func (mmap MarshalMap) Bytes(key string) ([]byte, error) { + val, exists := mmap.Value(key) + if !exists { + return []byte{}, fmt.Errorf(`"%s" is not set`, key) + } + + bytesValue, isBytes := val.([]byte) + if !isBytes { + return []byte{}, fmt.Errorf(`"%s" is expected to be a []byte`, key) + } + return bytesValue, nil +} + +// Slice is an alias for Array +func (mmap MarshalMap) Slice(key string) ([]interface{}, error) { + return mmap.Array(key) +} + +// Array returns a value at key that is expected to be a []interface{} +func (mmap MarshalMap) Array(key string) ([]interface{}, error) { + val, exists := mmap.Value(key) + if !exists { + return nil, fmt.Errorf(`"%s" is not set`, key) + } + + arrayValue, isArray := val.([]interface{}) + if !isArray { + return nil, fmt.Errorf(`"%s" is expected to be an array`, key) + } + return arrayValue, nil +} + +// Map returns a value at key that is expected to be a +// map[interface{}]interface{}. +func (mmap MarshalMap) Map(key string) (map[interface{}]interface{}, error) { + val, exists := mmap.Value(key) + if !exists { + return nil, fmt.Errorf(`"%s" is not set`, key) + } + + mapValue, isMap := val.(map[interface{}]interface{}) + if !isMap { + return nil, fmt.Errorf(`"%s" is expected to be a map`, key) + } + return mapValue, nil +} + +func castToStringArray(key string, value interface{}) ([]string, error) { + switch value.(type) { + case string: + return []string{value.(string)}, nil + + case []interface{}: + arrayVal := value.([]interface{}) + stringArray := make([]string, 0, len(arrayVal)) + + for _, val := range arrayVal { + strValue, isString := val.(string) + if !isString { + return nil, fmt.Errorf(`"%s" does not contain string keys`, key) + } + stringArray = append(stringArray, strValue) + } + return stringArray, nil + + case []string: + return value.([]string), nil + + default: + return nil, fmt.Errorf(`"%s" is not a valid string array type`, key) + } +} + +// StringSlice is an alias for StringArray +func (mmap MarshalMap) StringSlice(key string) ([]string, error) { + return mmap.StringArray(key) +} + +// StringArray returns a value at key that is expected to be a []string +// This function supports conversion (by copy) from +// * []interface{} +func (mmap MarshalMap) StringArray(key string) ([]string, error) { + val, exists := mmap.Value(key) + if !exists { + return nil, fmt.Errorf(`"%s" is not set`, key) + } + + return castToStringArray(key, val) +} + +func castToInt64Array(key string, value interface{}) ([]int64, error) { + switch value.(type) { + case int: + return []int64{value.(int64)}, nil + + case []interface{}: + arrayVal := value.([]interface{}) + intArray := make([]int64, 0, len(arrayVal)) + + for _, val := range arrayVal { + intValue, isInt := val.(int64) + if !isInt { + return nil, fmt.Errorf(`"%s" does not contain int keys`, key) + } + intArray = append(intArray, intValue) + } + return intArray, nil + + case []int64: + return value.([]int64), nil + + default: + return nil, fmt.Errorf(`"%s" is not a valid string array type`, key) + } +} + +// Int64Slice is an alias for Int64Array +func (mmap MarshalMap) Int64Slice(key string) ([]int64, error) { + return mmap.Int64Array(key) +} + +// Int64Array returns a value at key that is expected to be a []int64 +// This function supports conversion (by copy) from +// * []interface{} +func (mmap MarshalMap) Int64Array(key string) ([]int64, error) { + val, exists := mmap.Value(key) + if !exists { + return nil, fmt.Errorf(`"%s" is not set`, key) + } + + return castToInt64Array(key, val) +} + +// StringMap returns a value at key that is expected to be a map[string]string. +// This function supports conversion (by copy) from +// * map[interface{}]interface{} +// * map[string]interface{} +func (mmap MarshalMap) StringMap(key string) (map[string]string, error) { + val, exists := mmap.Value(key) + if !exists { + return nil, fmt.Errorf(`"%s" is not set`, key) + } + + switch val.(type) { + case map[string]string: + return val.(map[string]string), nil + + default: + valueMeta := reflect.ValueOf(val) + if valueMeta.Kind() != reflect.Map { + return nil, fmt.Errorf(`"%s" is expected to be a map[string]string but is %T`, key, val) + } + + result := make(map[string]string) + for _, keyMeta := range valueMeta.MapKeys() { + strKey, isString := keyMeta.Interface().(string) + if !isString { + return nil, fmt.Errorf(`"%s" is expected to be a map[string]string. Key is not a string`, key) + } + + value := valueMeta.MapIndex(keyMeta) + strValue, isString := value.Interface().(string) + if !isString { + return nil, fmt.Errorf(`"%s" is expected to be a map[string]string. Value is not a string`, key) + } + + result[strKey] = strValue + } + + return result, nil + } +} + +// StringSliceMap is an alias for StringArrayMap +func (mmap MarshalMap) StringSliceMap(key string) (map[string][]string, error) { + return mmap.StringArrayMap(key) +} + +// StringArrayMap returns a value at key that is expected to be a +// map[string][]string. This function supports conversion (by copy) from +// * map[interface{}][]interface{} +// * map[interface{}]interface{} +// * map[string]interface{} +func (mmap MarshalMap) StringArrayMap(key string) (map[string][]string, error) { + val, exists := mmap.Value(key) + if !exists { + return nil, fmt.Errorf(`"%s" is not set`, key) + } + + switch val.(type) { + case map[string][]string: + return val.(map[string][]string), nil + + default: + valueMeta := reflect.ValueOf(val) + if valueMeta.Kind() != reflect.Map { + return nil, fmt.Errorf(`"%s" is expected to be a map[string][]string but is %T`, key, val) + } + + result := make(map[string][]string) + for _, keyMeta := range valueMeta.MapKeys() { + strKey, isString := keyMeta.Interface().(string) + if !isString { + return nil, fmt.Errorf(`"%s" is expected to be a map[string][]string. Key is not a string`, key) + } + + value := valueMeta.MapIndex(keyMeta) + arrayValue, err := castToStringArray(strKey, value.Interface()) + if err != nil { + return nil, fmt.Errorf(`"%s" is expected to be a map[string][]string. Value is not a []string`, key) + } + + result[strKey] = arrayValue + } + + return result, nil + } +} + +// MarshalMap returns a value at key that is expected to be another MarshalMap +// This function supports conversion (by copy) from +// * map[interface{}]interface{} +func (mmap MarshalMap) MarshalMap(key string) (MarshalMap, error) { + val, exists := mmap.Value(key) + if !exists { + return nil, fmt.Errorf(`"%s" is not set`, key) + } + + return ConvertToMarshalMap(val, nil) +} + +// Value returns a value from a given value path. +// Fields can be accessed by their name. Nested fields can be accessed by using +// "/" as a separator. Arrays can be addressed using the standard array +// notation "[]". +// Examples: +// "key" -> mmap["key"] single value +// "key1/key2" -> mmap["key1"]["key2"] nested map +// "key1[0]" -> mmap["key1"][0] nested array +// "key1[0]key2" -> mmap["key1"][0]["key2"] nested array, nested map +func (mmap MarshalMap) Value(key string) (val interface{}, exists bool) { + exists = mmap.resolvePath(key, mmap, func(p, k reflect.Value, v interface{}) { + val = v + }) + return val, exists +} + +// Delete a value from a given path. +// The path must point to a map key. Deleting from arrays is not supported. +func (mmap MarshalMap) Delete(key string) { + mmap.resolvePath(key, mmap, func(p, k reflect.Value, v interface{}) { + if v != nil { + p.SetMapIndex(k, reflect.Value{}) + } + }) +} + +// Set a value for a given path. +// The path must point to a map key. Setting array elements is not supported. +func (mmap MarshalMap) Set(key string, val interface{}) { + mmap.resolvePath(key, mmap, func(p, k reflect.Value, v interface{}) { + p.SetMapIndex(k, reflect.ValueOf(val)) + }) +} + +func (mmap MarshalMap) resolvePathKey(key string) (int, int) { + keyEnd := len(key) + nextKeyStart := keyEnd + pathIdx := strings.IndexRune(key, MarshalMapSeparator) + arrayIdx := strings.IndexRune(key, MarshalMapArrayBegin) + + if pathIdx > -1 && pathIdx < keyEnd { + keyEnd = pathIdx + nextKeyStart = pathIdx + 1 // don't include slash + } + if arrayIdx > -1 && arrayIdx < keyEnd { + keyEnd = arrayIdx + nextKeyStart = arrayIdx // include bracket because of multidimensional arrays + } + + // a -> key: "a", remain: "" -- value + // a/b/c -> key: "a", remain: "b/c" -- nested map + // a[1]b/c -> key: "a", remain: "[1]b/c" -- nested array + + return keyEnd, nextKeyStart +} + +func (mmap MarshalMap) resolvePath(k string, v interface{}, action func(p, k reflect.Value, v interface{})) bool { + if len(k) == 0 { + action(reflect.Value{}, reflect.ValueOf(k), v) // ### return, found requested value ### + return true + } + + vValue := reflect.ValueOf(v) + switch vValue.Kind() { + case reflect.Array, reflect.Slice: + startIdx := strings.IndexRune(k, MarshalMapArrayBegin) // Must be first char, otherwise malformed + endIdx := strings.IndexRune(k, MarshalMapArrayEnd) // Must be > startIdx, otherwise malformed + + if startIdx == -1 || endIdx == -1 { + return false + } + + if startIdx == 0 && endIdx > startIdx { + index, err := strconv.Atoi(k[startIdx+1 : endIdx]) + + // [1] -> index: "1", remain: "" -- value + // [1]a/b -> index: "1", remain: "a/b" -- nested map + // [1][2] -> index: "1", remain: "[2]" -- nested array + + if err == nil && index < vValue.Len() { + item := vValue.Index(index).Interface() + key := k[endIdx+1:] + return mmap.resolvePath(key, item, action) // ### return, nested array ### + } + } + + case reflect.Map: + kValue := reflect.ValueOf(k) + if storedValue := vValue.MapIndex(kValue); storedValue.IsValid() { + action(vValue, kValue, storedValue.Interface()) + return true + } + + keyEnd, nextKeyStart := mmap.resolvePathKey(k) + if keyEnd == len(k) { + action(vValue, kValue, nil) // call action to support setting non-existing keys + return false // ### return, key not found ### + } + + nextKey := k[:keyEnd] + nkValue := reflect.ValueOf(nextKey) + + if storedValue := vValue.MapIndex(nkValue); storedValue.IsValid() { + remain := k[nextKeyStart:] + return mmap.resolvePath(remain, storedValue.Interface(), action) // ### return, nested map ### + } + } + + return false +} diff --git a/vendor/github.com/trivago/tgo/tcontainer/trie.go b/vendor/github.com/trivago/tgo/tcontainer/trie.go new file mode 100644 index 0000000000..f72170937c --- /dev/null +++ b/vendor/github.com/trivago/tgo/tcontainer/trie.go @@ -0,0 +1,227 @@ +// Copyright 2015-2018 trivago N.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package tcontainer + +// TrieNode represents a single node inside a trie. +// Each node can contain a payload which can be retrieved after a successfull +// match. In addition to that PathLen will contain the length of the match. +type TrieNode struct { + suffix []byte + children []*TrieNode + longestPath int + PathLen int + Payload interface{} +} + +// NewTrie creates a new root TrieNode +func NewTrie(data []byte, payload interface{}) *TrieNode { + return &TrieNode{ + suffix: data, + children: []*TrieNode{}, + longestPath: len(data), + PathLen: len(data), + Payload: payload, + } +} + +func (node *TrieNode) addNewChild(data []byte, payload interface{}, pathLen int) { + if node.longestPath < pathLen { + node.longestPath = pathLen + } + + idx := len(node.children) + node.children = append(node.children, nil) + + for idx > 0 { + nextIdx := idx - 1 + if node.children[nextIdx].longestPath > pathLen { + break + } + node.children[idx] = node.children[nextIdx] + idx = nextIdx + } + + node.children[idx] = &TrieNode{ + suffix: data, + children: []*TrieNode{}, + longestPath: pathLen, + PathLen: pathLen, + Payload: payload, + } +} + +func (node *TrieNode) replace(oldChild *TrieNode, newChild *TrieNode) { + for i, child := range node.children { + if child == oldChild { + node.children[i] = newChild + return // ### return, replaced ### + } + } +} + +// ForEach applies a function to each node in the tree including and below the +// passed node. +func (node *TrieNode) ForEach(callback func(*TrieNode)) { + callback(node) + for _, child := range node.children { + child.ForEach(callback) + } +} + +// Add adds a new data path to the trie. +// The TrieNode returned is the (new) root node so you should always reassign +// the root with the return value of Add. +func (node *TrieNode) Add(data []byte, payload interface{}) *TrieNode { + return node.addPath(data, payload, len(data), nil) +} + +func (node *TrieNode) addPath(data []byte, payload interface{}, pathLen int, parent *TrieNode) *TrieNode { + dataLen := len(data) + suffixLen := len(node.suffix) + testLen := suffixLen + if dataLen < suffixLen { + testLen = dataLen + } + + var splitIdx int + for splitIdx = 0; splitIdx < testLen; splitIdx++ { + if data[splitIdx] != node.suffix[splitIdx] { + break // ### break, split found ### + } + } + + if splitIdx == suffixLen { + // Continue down or stop here (full suffix match) + + if splitIdx == dataLen { + node.Payload = payload // may overwrite + return node // ### return, path already stored ### + } + + data = data[splitIdx:] + if suffixLen > 0 { + for _, child := range node.children { + if child.suffix[0] == data[0] { + child.addPath(data, payload, pathLen, node) + return node // ### return, continue on path ### + } + } + } + + node.addNewChild(data, payload, pathLen) + return node // ### return, new leaf ### + } + + if splitIdx == dataLen { + // Make current node a subpath of new data node (full data match) + // This case implies that dataLen < suffixLen as splitIdx == suffixLen + // did not match. + + node.suffix = node.suffix[splitIdx:] + + newParent := NewTrie(data, payload) + newParent.PathLen = pathLen + newParent.longestPath = node.longestPath + newParent.children = []*TrieNode{node} + + if parent != nil { + parent.replace(node, newParent) + } + return newParent // ### return, rotation ### + } + + // New parent required with both nodes as children (partial match) + + node.suffix = node.suffix[splitIdx:] + + newParent := NewTrie(data[:splitIdx], nil) + newParent.PathLen = 0 + newParent.longestPath = node.longestPath + newParent.children = []*TrieNode{node} + newParent.addNewChild(data[splitIdx:], payload, pathLen) + + if parent != nil { + parent.replace(node, newParent) + } + return newParent // ### return, new parent ### +} + +// Match compares the trie to the given data stream. +// Match returns true if data can be completely matched to the trie. +func (node *TrieNode) Match(data []byte) *TrieNode { + dataLen := len(data) + suffixLen := len(node.suffix) + if dataLen < suffixLen { + return nil // ### return, cannot be fully matched ### + } + + for i := 0; i < suffixLen; i++ { + if data[i] != node.suffix[i] { + return nil // ### return, no match ### + } + } + + if dataLen == suffixLen { + if node.PathLen > 0 { + return node // ### return, full match ### + } + return nil // ### return, invalid match ### + } + + data = data[suffixLen:] + numChildren := len(node.children) + for i := 0; i < numChildren; i++ { + matchedNode := node.children[i].Match(data) + if matchedNode != nil { + return matchedNode // ### return, match found ### + } + } + + return nil // ### return, no valid path ### +} + +// MatchStart compares the trie to the beginning of the given data stream. +// MatchStart returns true if the beginning of data can be matched to the trie. +func (node *TrieNode) MatchStart(data []byte) *TrieNode { + dataLen := len(data) + suffixLen := len(node.suffix) + if dataLen < suffixLen { + return nil // ### return, cannot be fully matched ### + } + + for i := 0; i < suffixLen; i++ { + if data[i] != node.suffix[i] { + return nil // ### return, no match ### + } + } + + // Match longest path first + + data = data[suffixLen:] + numChildren := len(node.children) + for i := 0; i < numChildren; i++ { + matchedNode := node.children[i].MatchStart(data) + if matchedNode != nil { + return matchedNode // ### return, match found ### + } + } + + // May be only a part of data but we have a valid match + + if node.PathLen > 0 { + return node // ### return, full match ### + } + return nil // ### return, no valid path ### +} diff --git a/vendor/github.com/trivago/tgo/treflect/clone.go b/vendor/github.com/trivago/tgo/treflect/clone.go new file mode 100644 index 0000000000..b887126263 --- /dev/null +++ b/vendor/github.com/trivago/tgo/treflect/clone.go @@ -0,0 +1,80 @@ +// Copyright 2015-2018 trivago N.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package treflect + +import ( + "reflect" +) + +// Clone does a deep copy of the given value. +// Please note that field have to be public in order to be copied. +// Private fields will be ignored. +func Clone(v interface{}) interface{} { + value := reflect.ValueOf(v) + copy := clone(value) + return copy.Interface() +} + +func clone(v reflect.Value) reflect.Value { + switch v.Kind() { + case reflect.Struct: + copy := reflect.New(v.Type()) + + for i := 0; i < v.Type().NumField(); i++ { + field := v.Field(i) + targetField := copy.Elem().Field(i) + if !targetField.CanSet() { + continue // ignore private fields + } + fieldCopy := clone(field) + targetField.Set(fieldCopy) + } + return copy.Elem() + + case reflect.Chan: + copy := reflect.MakeChan(v.Type(), v.Len()) + return copy + + case reflect.Map: + copy := reflect.MakeMap(v.Type()) + keys := v.MapKeys() + for _, k := range keys { + fieldCopy := clone(v.MapIndex(k)) + copy.SetMapIndex(k, fieldCopy) + } + return copy + + case reflect.Slice: + copy := reflect.MakeSlice(v.Type(), v.Len(), v.Len()) + for i := 0; i < v.Len(); i++ { + elementCopy := clone(v.Index(i)) + copy.Index(i).Set(elementCopy) + } + return copy + + case reflect.Array: + copy := reflect.New(v.Type()).Elem() + for i := 0; i < v.Len(); i++ { + elementCopy := clone(v.Index(i)) + copy.Index(i).Set(elementCopy) + } + return copy + + default: + copy := reflect.New(v.Type()) + copy.Elem().Set(v) + return copy.Elem() + } +} diff --git a/vendor/github.com/trivago/tgo/treflect/reflection.go b/vendor/github.com/trivago/tgo/treflect/reflection.go new file mode 100644 index 0000000000..48a11f477e --- /dev/null +++ b/vendor/github.com/trivago/tgo/treflect/reflection.go @@ -0,0 +1,371 @@ +// Copyright 2015-2018 trivago N.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package treflect + +import ( + "fmt" + "reflect" + "unsafe" +) + +// GetMissingMethods checks if a given object implements all methods of a +// given interface. It returns the interface coverage [0..1] as well as an array +// of error messages. If the interface is correctly implemented the coverage is +// 1 and the error message array is empty. +func GetMissingMethods(objType reflect.Type, ifaceType reflect.Type) (float32, []string) { + missing := []string{} + if objType.Implements(ifaceType) { + return 1.0, missing + } + + methodCount := ifaceType.NumMethod() + for mIdx := 0; mIdx < methodCount; mIdx++ { + ifaceMethod := ifaceType.Method(mIdx) + objMethod, exists := objType.MethodByName(ifaceMethod.Name) + signatureMismatch := false + + switch { + case !exists: + missing = append(missing, fmt.Sprintf("Missing: \"%s\" %v", ifaceMethod.Name, ifaceMethod.Type)) + continue // ### continue, error found ### + + case ifaceMethod.Type.NumOut() != objMethod.Type.NumOut(): + signatureMismatch = true + + case ifaceMethod.Type.NumIn()+1 != objMethod.Type.NumIn(): + signatureMismatch = true + + default: + for oIdx := 0; !signatureMismatch && oIdx < ifaceMethod.Type.NumOut(); oIdx++ { + signatureMismatch = ifaceMethod.Type.Out(oIdx) != objMethod.Type.Out(oIdx) + } + for iIdx := 0; !signatureMismatch && iIdx < ifaceMethod.Type.NumIn(); iIdx++ { + signatureMismatch = ifaceMethod.Type.In(iIdx) != objMethod.Type.In(iIdx+1) + } + } + + if signatureMismatch { + missing = append(missing, fmt.Sprintf("Invalid: \"%s\" %v is not %v", ifaceMethod.Name, objMethod.Type, ifaceMethod.Type)) + } + } + + return float32(methodCount-len(missing)) / float32(methodCount), missing +} + +// Int64 converts any signed number type to an int64. +// The second parameter is returned as false if a non-number type was given. +func Int64(v interface{}) (int64, bool) { + + switch reflect.TypeOf(v).Kind() { + case reflect.Int: + return int64(v.(int)), true + case reflect.Int8: + return int64(v.(int8)), true + case reflect.Int16: + return int64(v.(int16)), true + case reflect.Int32: + return int64(v.(int32)), true + case reflect.Int64: + return v.(int64), true + case reflect.Float32: + return int64(v.(float32)), true + case reflect.Float64: + return int64(v.(float64)), true + } + + return 0, false +} + +// Uint64 converts any unsigned number type to an uint64. +// The second parameter is returned as false if a non-number type was given. +func Uint64(v interface{}) (uint64, bool) { + + switch reflect.TypeOf(v).Kind() { + case reflect.Uint: + return uint64(v.(uint)), true + case reflect.Uint8: + return uint64(v.(uint8)), true + case reflect.Uint16: + return uint64(v.(uint16)), true + case reflect.Uint32: + return uint64(v.(uint32)), true + case reflect.Uint64: + return v.(uint64), true + } + + return 0, false +} + +// Float32 converts any number type to an float32. +// The second parameter is returned as false if a non-number type was given. +func Float32(v interface{}) (float32, bool) { + + switch reflect.TypeOf(v).Kind() { + case reflect.Int: + return float32(v.(int)), true + case reflect.Uint: + return float32(v.(uint)), true + case reflect.Int8: + return float32(v.(int8)), true + case reflect.Uint8: + return float32(v.(uint8)), true + case reflect.Int16: + return float32(v.(int16)), true + case reflect.Uint16: + return float32(v.(uint16)), true + case reflect.Int32: + return float32(v.(int32)), true + case reflect.Uint32: + return float32(v.(uint32)), true + case reflect.Int64: + return float32(v.(int64)), true + case reflect.Uint64: + return float32(v.(uint64)), true + case reflect.Float32: + return v.(float32), true + case reflect.Float64: + return float32(v.(float64)), true + } + + return 0, false +} + +// Float64 converts any number type to an float64. +// The second parameter is returned as false if a non-number type was given. +func Float64(v interface{}) (float64, bool) { + + switch reflect.TypeOf(v).Kind() { + case reflect.Int: + return float64(v.(int)), true + case reflect.Uint: + return float64(v.(uint)), true + case reflect.Int8: + return float64(v.(int8)), true + case reflect.Uint8: + return float64(v.(uint8)), true + case reflect.Int16: + return float64(v.(int16)), true + case reflect.Uint16: + return float64(v.(uint16)), true + case reflect.Int32: + return float64(v.(int32)), true + case reflect.Uint32: + return float64(v.(uint32)), true + case reflect.Int64: + return float64(v.(int64)), true + case reflect.Uint64: + return float64(v.(uint64)), true + case reflect.Float32: + return float64(v.(float32)), true + case reflect.Float64: + return v.(float64), true + } + + return 0, false +} + +// RemovePtrFromType will return the type of t and strips away any pointer(s) +// in front of the actual type. +func RemovePtrFromType(t interface{}) reflect.Type { + var v reflect.Type + if rt, isType := t.(reflect.Type); isType { + v = rt + } else { + v = reflect.TypeOf(t) + } + for v.Kind() == reflect.Ptr { + v = v.Elem() + } + return v +} + +// RemovePtrFromValue will return the value of t and strips away any pointer(s) +// in front of the actual type. +func RemovePtrFromValue(t interface{}) reflect.Value { + var v reflect.Value + if rv, isValue := t.(reflect.Value); isValue { + v = rv + } else { + v = reflect.ValueOf(t) + } + for v.Type().Kind() == reflect.Ptr { + v = v.Elem() + } + return v +} + +// UnsafeCopy will copy data from src to dst while ignoring type information. +// Both types need to be of the same size and dst and src have to be pointers. +// UnsafeCopy will panic if these requirements are not met. +func UnsafeCopy(dst, src interface{}) { + dstValue := reflect.ValueOf(dst) + srcValue := reflect.ValueOf(src) + UnsafeCopyValue(dstValue, srcValue) +} + +// UnsafeCopyValue will copy data from src to dst while ignoring type +// information. Both types need to be of the same size or this function will +// panic. Also both types must support dereferencing via reflect.Elem() +func UnsafeCopyValue(dstValue reflect.Value, srcValue reflect.Value) { + dstType := dstValue.Elem().Type() + srcType := srcValue.Type() + + var srcPtr uintptr + if srcValue.Kind() != reflect.Ptr { + // If we don't get a pointer to our source data we need to forcefully + // retrieve it by accessing the interface pointer. This is ok as we + // only read from it. + iface := srcValue.Interface() + srcPtr = reflect.ValueOf(&iface).Elem().InterfaceData()[1] // Pointer to data + } else { + srcType = srcValue.Elem().Type() + srcPtr = srcValue.Pointer() + } + + if dstType.Size() != srcType.Size() { + panic("Type size mismatch between " + dstType.String() + " and " + srcType.String()) + } + + dstAsSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ + Data: dstValue.Pointer(), + Len: int(dstType.Size()), + Cap: int(dstType.Size()), + })) + + srcAsSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ + Data: srcPtr, + Len: int(srcType.Size()), + Cap: int(srcType.Size()), + })) + + copy(dstAsSlice, srcAsSlice) +} + +// SetMemberByName sets member name of the given pointer-to-struct to the data +// passed to this function. The member may be private, too. +func SetMemberByName(ptrToStruct interface{}, name string, data interface{}) { + structVal := reflect.Indirect(reflect.ValueOf(ptrToStruct)) + member := structVal.FieldByName(name) + + SetValue(member, data) +} + +// SetMemberByIndex sets member idx of the given pointer-to-struct to the data +// passed to this function. The member may be private, too. +func SetMemberByIndex(ptrToStruct interface{}, idx int, data interface{}) { + structVal := reflect.Indirect(reflect.ValueOf(ptrToStruct)) + member := structVal.Field(idx) + + SetValue(member, data) +} + +// SetValue sets an addressable value to the data passed to this function. +// In contrast to golangs reflect package this will also work with private +// variables. Please note that this function may not support all types, yet. +func SetValue(member reflect.Value, data interface{}) { + if member.CanSet() { + member.Set(reflect.ValueOf(data).Convert(member.Type())) + return // ### return, easy way ### + } + + if !member.CanAddr() { + panic("SetValue requires addressable member type") + } + + ptrToMember := unsafe.Pointer(member.UnsafeAddr()) + dataValue := reflect.ValueOf(data) + + switch member.Kind() { + case reflect.Bool: + *(*bool)(ptrToMember) = dataValue.Bool() + + case reflect.Uint: + *(*uint)(ptrToMember) = uint(dataValue.Uint()) + + case reflect.Uint8: + *(*uint8)(ptrToMember) = uint8(dataValue.Uint()) + + case reflect.Uint16: + *(*uint16)(ptrToMember) = uint16(dataValue.Uint()) + + case reflect.Uint32: + *(*uint32)(ptrToMember) = uint32(dataValue.Uint()) + + case reflect.Uint64: + *(*uint64)(ptrToMember) = dataValue.Uint() + + case reflect.Int: + *(*int)(ptrToMember) = int(dataValue.Int()) + + case reflect.Int8: + *(*int8)(ptrToMember) = int8(dataValue.Int()) + + case reflect.Int16: + *(*int16)(ptrToMember) = int16(dataValue.Int()) + + case reflect.Int32: + *(*int32)(ptrToMember) = int32(dataValue.Int()) + + case reflect.Int64: + *(*int64)(ptrToMember) = dataValue.Int() + + case reflect.Float32: + *(*float32)(ptrToMember) = float32(dataValue.Float()) + + case reflect.Float64: + *(*float64)(ptrToMember) = dataValue.Float() + + case reflect.Complex64: + *(*complex64)(ptrToMember) = complex64(dataValue.Complex()) + + case reflect.Complex128: + *(*complex128)(ptrToMember) = dataValue.Complex() + + case reflect.String: + *(*string)(ptrToMember) = dataValue.String() + + case reflect.Map, reflect.Chan: + // Exploit the fact that "map" is actually "*runtime.hmap" and force + // overwrite that pointer in the passed struct. + // Same foes for "chan" which is actually "*runtime.hchan". + + // Note: Assigning a map or channel to another variable does NOT copy + // the contents so copying the pointer follows go's standard behavior. + dataAsPtr := unsafe.Pointer(dataValue.Pointer()) + *(**uintptr)(ptrToMember) = (*uintptr)(dataAsPtr) + + case reflect.Interface: + // Interfaces are basically two pointers, see runtime.iface. + // We want to modify exactly that data, which is returned by + // the InterfaceData() method. + + if dataValue.Kind() != reflect.Interface { + // A type reference was passed. In order to overwrite the memory + // Representation of an interface we need to generate it first. + // Reflect does not allow us to do that unless we use the + // InterfaceData method which exposes the internal representation + // of an interface. + interfaceData := reflect.ValueOf(&data).Elem().InterfaceData() + dataValue = reflect.ValueOf(interfaceData) + } + fallthrough + + default: + // Complex types are assigned memcpy style. + // Note: This should not break the garbage collector although we cannot + // be 100% sure on this. + UnsafeCopyValue(member.Addr(), dataValue) + } +} diff --git a/vendor/github.com/trivago/tgo/treflect/typeregistry.go b/vendor/github.com/trivago/tgo/treflect/typeregistry.go new file mode 100644 index 0000000000..d3e3d7eff8 --- /dev/null +++ b/vendor/github.com/trivago/tgo/treflect/typeregistry.go @@ -0,0 +1,97 @@ +// Copyright 2015-2018 trivago N.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package treflect + +import ( + "fmt" + "reflect" + "strings" +) + +// TypeRegistry is a name to type registry used to create objects by name. +type TypeRegistry struct { + namedType map[string]reflect.Type +} + +// NewTypeRegistry creates a new TypeRegistry. Note that there is a global type +// registry available in the main tgo package (tgo.TypeRegistry). +func NewTypeRegistry() TypeRegistry { + return TypeRegistry{ + namedType: make(map[string]reflect.Type), + } +} + +// Register a plugin to the TypeRegistry by passing an uninitialized object. +func (registry TypeRegistry) Register(typeInstance interface{}) { + registry.RegisterWithDepth(typeInstance, 1) +} + +// RegisterWithDepth to register a plugin to the TypeRegistry by passing an uninitialized object. +func (registry TypeRegistry) RegisterWithDepth(typeInstance interface{}, depth int) { + structType := reflect.TypeOf(typeInstance) + packageName := structType.PkgPath() + typeName := structType.Name() + + pathTokens := strings.Split(packageName, "/") + maxDepth := 3 + if len(pathTokens) < maxDepth { + maxDepth = len(pathTokens) + } + + for n := depth; n <= maxDepth; n++ { + shortTypeName := strings.Join(pathTokens[len(pathTokens)-n:], ".") + "." + typeName + registry.namedType[shortTypeName] = structType + } +} + +// New creates an uninitialized object by class name. +// The class name has to be "package.class" or "package/subpackage.class". +// The gollum package is omitted from the package path. +func (registry TypeRegistry) New(typeName string) (interface{}, error) { + structType, exists := registry.namedType[typeName] + if exists { + return reflect.New(structType).Interface(), nil + } + return nil, fmt.Errorf("Unknown class: %s", typeName) +} + +// GetTypeOf returns only the type asscociated with the given name. +// If the name is not registered, nil is returned. +// The type returned will be a pointer type. +func (registry TypeRegistry) GetTypeOf(typeName string) reflect.Type { + if structType, exists := registry.namedType[typeName]; exists { + return reflect.PtrTo(structType) + } + return nil +} + +// IsTypeRegistered returns true if a type is registered to this registry. +// Note that GetTypeOf can do the same thing by checking for nil but also +// returns the type, so in many cases you will want to call this function. +func (registry TypeRegistry) IsTypeRegistered(typeName string) bool { + _, exists := registry.namedType[typeName] + return exists +} + +// GetRegistered returns the names of all registered types for a given package +func (registry TypeRegistry) GetRegistered(packageName string) []string { + var result []string + for key := range registry.namedType { + if strings.HasPrefix(key, packageName) { + result = append(result, key) + } + } + return result +} diff --git a/vendor/github.com/yosida95/uritemplate/v3/README.rst b/vendor/github.com/yosida95/uritemplate/v3/README.rst deleted file mode 100644 index 6815d0a465..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/README.rst +++ /dev/null @@ -1,46 +0,0 @@ -uritemplate -=========== - -`uritemplate`_ is a Go implementation of `URI Template`_ [RFC6570] with -full functionality of URI Template Level 4. - -uritemplate can also generate a regexp that matches expansion of the -URI Template from a URI Template. - -Getting Started ---------------- - -Installation -~~~~~~~~~~~~ - -.. code-block:: sh - - $ go get -u github.com/yosida95/uritemplate/v3 - -Documentation -~~~~~~~~~~~~~ - -The documentation is available on GoDoc_. - -Examples --------- - -See `examples on GoDoc`_. - -License -------- - -`uritemplate`_ is distributed under the BSD 3-Clause license. -PLEASE READ ./LICENSE carefully and follow its clauses to use this software. - -Author ------- - -yosida95_ - - -.. _`URI Template`: https://tools.ietf.org/html/rfc6570 -.. _Godoc: https://godoc.org/github.com/yosida95/uritemplate -.. _`examples on GoDoc`: https://godoc.org/github.com/yosida95/uritemplate#pkg-examples -.. _yosida95: https://yosida95.com/ -.. _uritemplate: https://github.com/yosida95/uritemplate diff --git a/vendor/github.com/yosida95/uritemplate/v3/compile.go b/vendor/github.com/yosida95/uritemplate/v3/compile.go deleted file mode 100644 index bd774d15d0..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/compile.go +++ /dev/null @@ -1,224 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "fmt" - "unicode/utf8" -) - -type compiler struct { - prog *prog -} - -func (c *compiler) init() { - c.prog = &prog{} -} - -func (c *compiler) op(opcode progOpcode) uint32 { - i := len(c.prog.op) - c.prog.op = append(c.prog.op, progOp{code: opcode}) - return uint32(i) -} - -func (c *compiler) opWithRune(opcode progOpcode, r rune) uint32 { - addr := c.op(opcode) - (&c.prog.op[addr]).r = r - return addr -} - -func (c *compiler) opWithRuneClass(opcode progOpcode, rc runeClass) uint32 { - addr := c.op(opcode) - (&c.prog.op[addr]).rc = rc - return addr -} - -func (c *compiler) opWithAddr(opcode progOpcode, absaddr uint32) uint32 { - addr := c.op(opcode) - (&c.prog.op[addr]).i = absaddr - return addr -} - -func (c *compiler) opWithAddrDelta(opcode progOpcode, delta uint32) uint32 { - return c.opWithAddr(opcode, uint32(len(c.prog.op))+delta) -} - -func (c *compiler) opWithName(opcode progOpcode, name string) uint32 { - addr := c.op(opcode) - (&c.prog.op[addr]).name = name - return addr -} - -func (c *compiler) compileString(str string) { - for i := 0; i < len(str); { - // NOTE(yosida95): It is confirmed at parse time that literals - // consist of only valid-UTF8 runes. - r, size := utf8.DecodeRuneInString(str[i:]) - c.opWithRune(opRune, r) - i += size - } -} - -func (c *compiler) compileRuneClass(rc runeClass, maxlen int) { - for i := 0; i < maxlen; i++ { - if i > 0 { - c.opWithAddrDelta(opSplit, 7) - } - c.opWithAddrDelta(opSplit, 3) // raw rune or pct-encoded - c.opWithRuneClass(opRuneClass, rc) // raw rune - c.opWithAddrDelta(opJmp, 4) // - c.opWithRune(opRune, '%') // pct-encoded - c.opWithRuneClass(opRuneClass, runeClassPctE) // - c.opWithRuneClass(opRuneClass, runeClassPctE) // - } -} - -func (c *compiler) compileRuneClassInfinite(rc runeClass) { - start := c.opWithAddrDelta(opSplit, 3) // raw rune or pct-encoded - c.opWithRuneClass(opRuneClass, rc) // raw rune - c.opWithAddrDelta(opJmp, 4) // - c.opWithRune(opRune, '%') // pct-encoded - c.opWithRuneClass(opRuneClass, runeClassPctE) // - c.opWithRuneClass(opRuneClass, runeClassPctE) // - c.opWithAddrDelta(opSplit, 2) // loop - c.opWithAddr(opJmp, start) // -} - -func (c *compiler) compileVarspecValue(spec varspec, expr *expression) { - var specname string - if spec.maxlen > 0 { - specname = fmt.Sprintf("%s:%d", spec.name, spec.maxlen) - } else { - specname = spec.name - } - - c.prog.numCap++ - - c.opWithName(opCapStart, specname) - - split := c.op(opSplit) - if spec.maxlen > 0 { - c.compileRuneClass(expr.allow, spec.maxlen) - } else { - c.compileRuneClassInfinite(expr.allow) - } - - capEnd := c.opWithName(opCapEnd, specname) - c.prog.op[split].i = capEnd -} - -func (c *compiler) compileVarspec(spec varspec, expr *expression) { - switch { - case expr.named && spec.explode: - split1 := c.op(opSplit) - noop := c.op(opNoop) - c.compileString(spec.name) - - split2 := c.op(opSplit) - c.opWithRune(opRune, '=') - c.compileVarspecValue(spec, expr) - - split3 := c.op(opSplit) - c.compileString(expr.sep) - c.opWithAddr(opJmp, noop) - - c.prog.op[split2].i = uint32(len(c.prog.op)) - c.compileString(expr.ifemp) - c.opWithAddr(opJmp, split3) - - c.prog.op[split1].i = uint32(len(c.prog.op)) - c.prog.op[split3].i = uint32(len(c.prog.op)) - - case expr.named && !spec.explode: - c.compileString(spec.name) - - split2 := c.op(opSplit) - c.opWithRune(opRune, '=') - - split3 := c.op(opSplit) - - split4 := c.op(opSplit) - c.compileVarspecValue(spec, expr) - - split5 := c.op(opSplit) - c.prog.op[split4].i = split5 - c.compileString(",") - c.opWithAddr(opJmp, split4) - - c.prog.op[split3].i = uint32(len(c.prog.op)) - c.compileString(",") - jmp1 := c.op(opJmp) - - c.prog.op[split2].i = uint32(len(c.prog.op)) - c.compileString(expr.ifemp) - - c.prog.op[split5].i = uint32(len(c.prog.op)) - c.prog.op[jmp1].i = uint32(len(c.prog.op)) - - case !expr.named: - start := uint32(len(c.prog.op)) - c.compileVarspecValue(spec, expr) - - split1 := c.op(opSplit) - jmp := c.op(opJmp) - - c.prog.op[split1].i = uint32(len(c.prog.op)) - if spec.explode { - c.compileString(expr.sep) - } else { - c.opWithRune(opRune, ',') - } - c.opWithAddr(opJmp, start) - - c.prog.op[jmp].i = uint32(len(c.prog.op)) - } -} - -func (c *compiler) compileExpression(expr *expression) { - if len(expr.vars) < 1 { - return - } - - split1 := c.op(opSplit) - c.compileString(expr.first) - - for i, size := 0, len(expr.vars); i < size; i++ { - spec := expr.vars[i] - - split2 := c.op(opSplit) - if i > 0 { - split3 := c.op(opSplit) - c.compileString(expr.sep) - c.prog.op[split3].i = uint32(len(c.prog.op)) - } - c.compileVarspec(spec, expr) - c.prog.op[split2].i = uint32(len(c.prog.op)) - } - - c.prog.op[split1].i = uint32(len(c.prog.op)) -} - -func (c *compiler) compileLiterals(lt literals) { - c.compileString(string(lt)) -} - -func (c *compiler) compile(tmpl *Template) { - c.op(opLineBegin) - for i := range tmpl.exprs { - expr := tmpl.exprs[i] - switch expr := expr.(type) { - default: - panic("unhandled expression") - case *expression: - c.compileExpression(expr) - case literals: - c.compileLiterals(expr) - } - } - c.op(opLineEnd) - c.op(opEnd) -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/equals.go b/vendor/github.com/yosida95/uritemplate/v3/equals.go deleted file mode 100644 index aa59a5c030..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/equals.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -type CompareFlags uint8 - -const ( - CompareVarname CompareFlags = 1 << iota -) - -// Equals reports whether or not two URI Templates t1 and t2 are equivalent. -func Equals(t1 *Template, t2 *Template, flags CompareFlags) bool { - if len(t1.exprs) != len(t2.exprs) { - return false - } - for i := 0; i < len(t1.exprs); i++ { - switch t1 := t1.exprs[i].(type) { - case literals: - t2, ok := t2.exprs[i].(literals) - if !ok { - return false - } - if t1 != t2 { - return false - } - case *expression: - t2, ok := t2.exprs[i].(*expression) - if !ok { - return false - } - if t1.op != t2.op || len(t1.vars) != len(t2.vars) { - return false - } - for n := 0; n < len(t1.vars); n++ { - v1 := t1.vars[n] - v2 := t2.vars[n] - if flags&CompareVarname == CompareVarname && v1.name != v2.name { - return false - } - if v1.maxlen != v2.maxlen || v1.explode != v2.explode { - return false - } - } - default: - panic("unhandled case") - } - } - return true -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/error.go b/vendor/github.com/yosida95/uritemplate/v3/error.go deleted file mode 100644 index 2fd34a8080..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/error.go +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "fmt" -) - -func errorf(pos int, format string, a ...interface{}) error { - msg := fmt.Sprintf(format, a...) - return fmt.Errorf("uritemplate:%d:%s", pos, msg) -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/escape.go b/vendor/github.com/yosida95/uritemplate/v3/escape.go deleted file mode 100644 index 6d27e693af..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/escape.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "strings" - "unicode" - "unicode/utf8" -) - -var ( - hex = []byte("0123456789ABCDEF") - // reserved = gen-delims / sub-delims - // gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" - // sub-delims = "!" / "$" / "&" / "’" / "(" / ")" - // / "*" / "+" / "," / ";" / "=" - rangeReserved = &unicode.RangeTable{ - R16: []unicode.Range16{ - {Lo: 0x21, Hi: 0x21, Stride: 1}, // '!' - {Lo: 0x23, Hi: 0x24, Stride: 1}, // '#' - '$' - {Lo: 0x26, Hi: 0x2C, Stride: 1}, // '&' - ',' - {Lo: 0x2F, Hi: 0x2F, Stride: 1}, // '/' - {Lo: 0x3A, Hi: 0x3B, Stride: 1}, // ':' - ';' - {Lo: 0x3D, Hi: 0x3D, Stride: 1}, // '=' - {Lo: 0x3F, Hi: 0x40, Stride: 1}, // '?' - '@' - {Lo: 0x5B, Hi: 0x5B, Stride: 1}, // '[' - {Lo: 0x5D, Hi: 0x5D, Stride: 1}, // ']' - }, - LatinOffset: 9, - } - reReserved = `\x21\x23\x24\x26-\x2c\x2f\x3a\x3b\x3d\x3f\x40\x5b\x5d` - // ALPHA = %x41-5A / %x61-7A - // DIGIT = %x30-39 - // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - rangeUnreserved = &unicode.RangeTable{ - R16: []unicode.Range16{ - {Lo: 0x2D, Hi: 0x2E, Stride: 1}, // '-' - '.' - {Lo: 0x30, Hi: 0x39, Stride: 1}, // '0' - '9' - {Lo: 0x41, Hi: 0x5A, Stride: 1}, // 'A' - 'Z' - {Lo: 0x5F, Hi: 0x5F, Stride: 1}, // '_' - {Lo: 0x61, Hi: 0x7A, Stride: 1}, // 'a' - 'z' - {Lo: 0x7E, Hi: 0x7E, Stride: 1}, // '~' - }, - } - reUnreserved = `\x2d\x2e\x30-\x39\x41-\x5a\x5f\x61-\x7a\x7e` -) - -type runeClass uint8 - -const ( - runeClassU runeClass = 1 << iota - runeClassR - runeClassPctE - runeClassLast - - runeClassUR = runeClassU | runeClassR -) - -var runeClassNames = []string{ - "U", - "R", - "pct-encoded", -} - -func (rc runeClass) String() string { - ret := make([]string, 0, len(runeClassNames)) - for i, j := 0, runeClass(1); j < runeClassLast; j <<= 1 { - if rc&j == j { - ret = append(ret, runeClassNames[i]) - } - i++ - } - return strings.Join(ret, "+") -} - -func pctEncode(w *strings.Builder, r rune) { - if s := r >> 24 & 0xff; s > 0 { - w.Write([]byte{'%', hex[s/16], hex[s%16]}) - } - if s := r >> 16 & 0xff; s > 0 { - w.Write([]byte{'%', hex[s/16], hex[s%16]}) - } - if s := r >> 8 & 0xff; s > 0 { - w.Write([]byte{'%', hex[s/16], hex[s%16]}) - } - if s := r & 0xff; s > 0 { - w.Write([]byte{'%', hex[s/16], hex[s%16]}) - } -} - -func unhex(c byte) byte { - switch { - case '0' <= c && c <= '9': - return c - '0' - case 'a' <= c && c <= 'f': - return c - 'a' + 10 - case 'A' <= c && c <= 'F': - return c - 'A' + 10 - } - return 0 -} - -func ishex(c byte) bool { - switch { - case '0' <= c && c <= '9': - return true - case 'a' <= c && c <= 'f': - return true - case 'A' <= c && c <= 'F': - return true - default: - return false - } -} - -func pctDecode(s string) string { - size := len(s) - for i := 0; i < len(s); { - switch s[i] { - case '%': - size -= 2 - i += 3 - default: - i++ - } - } - if size == len(s) { - return s - } - - buf := make([]byte, size) - j := 0 - for i := 0; i < len(s); { - switch c := s[i]; c { - case '%': - buf[j] = unhex(s[i+1])<<4 | unhex(s[i+2]) - i += 3 - j++ - default: - buf[j] = c - i++ - j++ - } - } - return string(buf) -} - -type escapeFunc func(*strings.Builder, string) error - -func escapeLiteral(w *strings.Builder, v string) error { - w.WriteString(v) - return nil -} - -func escapeExceptU(w *strings.Builder, v string) error { - for i := 0; i < len(v); { - r, size := utf8.DecodeRuneInString(v[i:]) - if r == utf8.RuneError { - return errorf(i, "invalid encoding") - } - if unicode.Is(rangeUnreserved, r) { - w.WriteRune(r) - } else { - pctEncode(w, r) - } - i += size - } - return nil -} - -func escapeExceptUR(w *strings.Builder, v string) error { - for i := 0; i < len(v); { - r, size := utf8.DecodeRuneInString(v[i:]) - if r == utf8.RuneError { - return errorf(i, "invalid encoding") - } - // TODO(yosida95): is pct-encoded triplets allowed here? - if unicode.In(r, rangeUnreserved, rangeReserved) { - w.WriteRune(r) - } else { - pctEncode(w, r) - } - i += size - } - return nil -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/expression.go b/vendor/github.com/yosida95/uritemplate/v3/expression.go deleted file mode 100644 index 4858c2ddef..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/expression.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "regexp" - "strconv" - "strings" -) - -type template interface { - expand(*strings.Builder, Values) error - regexp(*strings.Builder) -} - -type literals string - -func (l literals) expand(b *strings.Builder, _ Values) error { - b.WriteString(string(l)) - return nil -} - -func (l literals) regexp(b *strings.Builder) { - b.WriteString("(?:") - b.WriteString(regexp.QuoteMeta(string(l))) - b.WriteByte(')') -} - -type varspec struct { - name string - maxlen int - explode bool -} - -type expression struct { - vars []varspec - op parseOp - first string - sep string - named bool - ifemp string - escape escapeFunc - allow runeClass -} - -func (e *expression) init() { - switch e.op { - case parseOpSimple: - e.sep = "," - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpPlus: - e.sep = "," - e.escape = escapeExceptUR - e.allow = runeClassUR - case parseOpCrosshatch: - e.first = "#" - e.sep = "," - e.escape = escapeExceptUR - e.allow = runeClassUR - case parseOpDot: - e.first = "." - e.sep = "." - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpSlash: - e.first = "/" - e.sep = "/" - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpSemicolon: - e.first = ";" - e.sep = ";" - e.named = true - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpQuestion: - e.first = "?" - e.sep = "&" - e.named = true - e.ifemp = "=" - e.escape = escapeExceptU - e.allow = runeClassU - case parseOpAmpersand: - e.first = "&" - e.sep = "&" - e.named = true - e.ifemp = "=" - e.escape = escapeExceptU - e.allow = runeClassU - } -} - -func (e *expression) expand(w *strings.Builder, values Values) error { - first := true - for _, varspec := range e.vars { - value := values.Get(varspec.name) - if !value.Valid() { - continue - } - - if first { - w.WriteString(e.first) - first = false - } else { - w.WriteString(e.sep) - } - - if err := value.expand(w, varspec, e); err != nil { - return err - } - - } - return nil -} - -func (e *expression) regexp(b *strings.Builder) { - if e.first != "" { - b.WriteString("(?:") // $1 - b.WriteString(regexp.QuoteMeta(e.first)) - } - b.WriteByte('(') // $2 - runeClassToRegexp(b, e.allow, e.named || e.vars[0].explode) - if len(e.vars) > 1 || e.vars[0].explode { - max := len(e.vars) - 1 - for i := 0; i < len(e.vars); i++ { - if e.vars[i].explode { - max = -1 - break - } - } - - b.WriteString("(?:") // $3 - b.WriteString(regexp.QuoteMeta(e.sep)) - runeClassToRegexp(b, e.allow, e.named || max < 0) - b.WriteByte(')') // $3 - if max > 0 { - b.WriteString("{0,") - b.WriteString(strconv.Itoa(max)) - b.WriteByte('}') - } else { - b.WriteByte('*') - } - } - b.WriteByte(')') // $2 - if e.first != "" { - b.WriteByte(')') // $1 - } - b.WriteByte('?') -} - -func runeClassToRegexp(b *strings.Builder, class runeClass, named bool) { - b.WriteString("(?:(?:[") - if class&runeClassR == 0 { - b.WriteString(`\x2c`) - if named { - b.WriteString(`\x3d`) - } - } - if class&runeClassU == runeClassU { - b.WriteString(reUnreserved) - } - if class&runeClassR == runeClassR { - b.WriteString(reReserved) - } - b.WriteString("]") - b.WriteString("|%[[:xdigit:]][[:xdigit:]]") - b.WriteString(")*)") -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/machine.go b/vendor/github.com/yosida95/uritemplate/v3/machine.go deleted file mode 100644 index 7b1d0b518d..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/machine.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -// threadList implements https://research.swtch.com/sparse. -type threadList struct { - dense []threadEntry - sparse []uint32 -} - -type threadEntry struct { - pc uint32 - t *thread -} - -type thread struct { - op *progOp - cap map[string][]int -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/match.go b/vendor/github.com/yosida95/uritemplate/v3/match.go deleted file mode 100644 index 02fe6385a3..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/match.go +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "bytes" - "unicode" - "unicode/utf8" -) - -type matcher struct { - prog *prog - - list1 threadList - list2 threadList - matched bool - cap map[string][]int - - input string -} - -func (m *matcher) at(pos int) (rune, int, bool) { - if l := len(m.input); pos < l { - c := m.input[pos] - if c < utf8.RuneSelf { - return rune(c), 1, pos+1 < l - } - r, size := utf8.DecodeRuneInString(m.input[pos:]) - return r, size, pos+size < l - } - return -1, 0, false -} - -func (m *matcher) add(list *threadList, pc uint32, pos int, next bool, cap map[string][]int) { - if i := list.sparse[pc]; i < uint32(len(list.dense)) && list.dense[i].pc == pc { - return - } - - n := len(list.dense) - list.dense = list.dense[:n+1] - list.sparse[pc] = uint32(n) - - e := &list.dense[n] - e.pc = pc - e.t = nil - - op := &m.prog.op[pc] - switch op.code { - default: - panic("unhandled opcode") - case opRune, opRuneClass, opEnd: - e.t = &thread{ - op: &m.prog.op[pc], - cap: make(map[string][]int, len(m.cap)), - } - for k, v := range cap { - e.t.cap[k] = make([]int, len(v)) - copy(e.t.cap[k], v) - } - case opLineBegin: - if pos == 0 { - m.add(list, pc+1, pos, next, cap) - } - case opLineEnd: - if !next { - m.add(list, pc+1, pos, next, cap) - } - case opCapStart, opCapEnd: - ocap := make(map[string][]int, len(m.cap)) - for k, v := range cap { - ocap[k] = make([]int, len(v)) - copy(ocap[k], v) - } - ocap[op.name] = append(ocap[op.name], pos) - m.add(list, pc+1, pos, next, ocap) - case opSplit: - m.add(list, pc+1, pos, next, cap) - m.add(list, op.i, pos, next, cap) - case opJmp: - m.add(list, op.i, pos, next, cap) - case opJmpIfNotDefined: - m.add(list, pc+1, pos, next, cap) - m.add(list, op.i, pos, next, cap) - case opJmpIfNotFirst: - m.add(list, pc+1, pos, next, cap) - m.add(list, op.i, pos, next, cap) - case opJmpIfNotEmpty: - m.add(list, op.i, pos, next, cap) - m.add(list, pc+1, pos, next, cap) - case opNoop: - m.add(list, pc+1, pos, next, cap) - } -} - -func (m *matcher) step(clist *threadList, nlist *threadList, r rune, pos int, nextPos int, next bool) { - debug.Printf("===== %q =====", string(r)) - for i := 0; i < len(clist.dense); i++ { - e := clist.dense[i] - if debug { - var buf bytes.Buffer - dumpProg(&buf, m.prog, e.pc) - debug.Printf("\n%s", buf.String()) - } - if e.t == nil { - continue - } - - t := e.t - op := t.op - switch op.code { - default: - panic("unhandled opcode") - case opRune: - if op.r == r { - m.add(nlist, e.pc+1, nextPos, next, t.cap) - } - case opRuneClass: - ret := false - if !ret && op.rc&runeClassU == runeClassU { - ret = ret || unicode.Is(rangeUnreserved, r) - } - if !ret && op.rc&runeClassR == runeClassR { - ret = ret || unicode.Is(rangeReserved, r) - } - if !ret && op.rc&runeClassPctE == runeClassPctE { - ret = ret || unicode.Is(unicode.ASCII_Hex_Digit, r) - } - if ret { - m.add(nlist, e.pc+1, nextPos, next, t.cap) - } - case opEnd: - m.matched = true - for k, v := range t.cap { - m.cap[k] = make([]int, len(v)) - copy(m.cap[k], v) - } - clist.dense = clist.dense[:0] - } - } - clist.dense = clist.dense[:0] -} - -func (m *matcher) match() bool { - pos := 0 - clist, nlist := &m.list1, &m.list2 - for { - if len(clist.dense) == 0 && m.matched { - break - } - r, width, next := m.at(pos) - if !m.matched { - m.add(clist, 0, pos, next, m.cap) - } - m.step(clist, nlist, r, pos, pos+width, next) - - if width < 1 { - break - } - pos += width - - clist, nlist = nlist, clist - } - return m.matched -} - -func (tmpl *Template) Match(expansion string) Values { - tmpl.mu.Lock() - if tmpl.prog == nil { - c := compiler{} - c.init() - c.compile(tmpl) - tmpl.prog = c.prog - } - prog := tmpl.prog - tmpl.mu.Unlock() - - n := len(prog.op) - m := matcher{ - prog: prog, - list1: threadList{ - dense: make([]threadEntry, 0, n), - sparse: make([]uint32, n), - }, - list2: threadList{ - dense: make([]threadEntry, 0, n), - sparse: make([]uint32, n), - }, - cap: make(map[string][]int, prog.numCap), - input: expansion, - } - if !m.match() { - return nil - } - - match := make(Values, len(m.cap)) - for name, indices := range m.cap { - v := Value{V: make([]string, len(indices)/2)} - for i := range v.V { - v.V[i] = pctDecode(expansion[indices[2*i]:indices[2*i+1]]) - } - if len(v.V) == 1 { - v.T = ValueTypeString - } else { - v.T = ValueTypeList - } - match[name] = v - } - return match -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/parse.go b/vendor/github.com/yosida95/uritemplate/v3/parse.go deleted file mode 100644 index fd38a682f1..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/parse.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "fmt" - "unicode" - "unicode/utf8" -) - -type parseOp int - -const ( - parseOpSimple parseOp = iota - parseOpPlus - parseOpCrosshatch - parseOpDot - parseOpSlash - parseOpSemicolon - parseOpQuestion - parseOpAmpersand -) - -var ( - rangeVarchar = &unicode.RangeTable{ - R16: []unicode.Range16{ - {Lo: 0x0030, Hi: 0x0039, Stride: 1}, // '0' - '9' - {Lo: 0x0041, Hi: 0x005A, Stride: 1}, // 'A' - 'Z' - {Lo: 0x005F, Hi: 0x005F, Stride: 1}, // '_' - {Lo: 0x0061, Hi: 0x007A, Stride: 1}, // 'a' - 'z' - }, - LatinOffset: 4, - } - rangeLiterals = &unicode.RangeTable{ - R16: []unicode.Range16{ - {Lo: 0x0021, Hi: 0x0021, Stride: 1}, // '!' - {Lo: 0x0023, Hi: 0x0024, Stride: 1}, // '#' - '$' - {Lo: 0x0026, Hi: 0x003B, Stride: 1}, // '&' ''' '(' - ';'. '''/27 used to be excluded but an errata is in the review process https://www.rfc-editor.org/errata/eid6937 - {Lo: 0x003D, Hi: 0x003D, Stride: 1}, // '=' - {Lo: 0x003F, Hi: 0x005B, Stride: 1}, // '?' - '[' - {Lo: 0x005D, Hi: 0x005D, Stride: 1}, // ']' - {Lo: 0x005F, Hi: 0x005F, Stride: 1}, // '_' - {Lo: 0x0061, Hi: 0x007A, Stride: 1}, // 'a' - 'z' - {Lo: 0x007E, Hi: 0x007E, Stride: 1}, // '~' - {Lo: 0x00A0, Hi: 0xD7FF, Stride: 1}, // ucschar - {Lo: 0xE000, Hi: 0xF8FF, Stride: 1}, // iprivate - {Lo: 0xF900, Hi: 0xFDCF, Stride: 1}, // ucschar - {Lo: 0xFDF0, Hi: 0xFFEF, Stride: 1}, // ucschar - }, - R32: []unicode.Range32{ - {Lo: 0x00010000, Hi: 0x0001FFFD, Stride: 1}, // ucschar - {Lo: 0x00020000, Hi: 0x0002FFFD, Stride: 1}, // ucschar - {Lo: 0x00030000, Hi: 0x0003FFFD, Stride: 1}, // ucschar - {Lo: 0x00040000, Hi: 0x0004FFFD, Stride: 1}, // ucschar - {Lo: 0x00050000, Hi: 0x0005FFFD, Stride: 1}, // ucschar - {Lo: 0x00060000, Hi: 0x0006FFFD, Stride: 1}, // ucschar - {Lo: 0x00070000, Hi: 0x0007FFFD, Stride: 1}, // ucschar - {Lo: 0x00080000, Hi: 0x0008FFFD, Stride: 1}, // ucschar - {Lo: 0x00090000, Hi: 0x0009FFFD, Stride: 1}, // ucschar - {Lo: 0x000A0000, Hi: 0x000AFFFD, Stride: 1}, // ucschar - {Lo: 0x000B0000, Hi: 0x000BFFFD, Stride: 1}, // ucschar - {Lo: 0x000C0000, Hi: 0x000CFFFD, Stride: 1}, // ucschar - {Lo: 0x000D0000, Hi: 0x000DFFFD, Stride: 1}, // ucschar - {Lo: 0x000E1000, Hi: 0x000EFFFD, Stride: 1}, // ucschar - {Lo: 0x000F0000, Hi: 0x000FFFFD, Stride: 1}, // iprivate - {Lo: 0x00100000, Hi: 0x0010FFFD, Stride: 1}, // iprivate - }, - LatinOffset: 10, - } -) - -type parser struct { - r string - start int - stop int - state parseState -} - -func (p *parser) errorf(i rune, format string, a ...interface{}) error { - return fmt.Errorf("%s: %s%s", fmt.Sprintf(format, a...), p.r[0:p.stop], string(i)) -} - -func (p *parser) rune() (rune, int) { - r, size := utf8.DecodeRuneInString(p.r[p.stop:]) - if r != utf8.RuneError { - p.stop += size - } - return r, size -} - -func (p *parser) unread(r rune) { - p.stop -= utf8.RuneLen(r) -} - -type parseState int - -const ( - parseStateDefault = parseState(iota) - parseStateOperator - parseStateVarList - parseStateVarName - parseStatePrefix -) - -func (p *parser) setState(state parseState) { - p.state = state - p.start = p.stop -} - -func (p *parser) parseURITemplate() (*Template, error) { - tmpl := Template{ - raw: p.r, - exprs: []template{}, - } - - var exp *expression - for { - r, size := p.rune() - if r == utf8.RuneError { - if size == 0 { - if p.state != parseStateDefault { - return nil, p.errorf('_', "incomplete expression") - } - if p.start < p.stop { - tmpl.exprs = append(tmpl.exprs, literals(p.r[p.start:p.stop])) - } - return &tmpl, nil - } - return nil, p.errorf('_', "invalid UTF-8 sequence") - } - - switch p.state { - case parseStateDefault: - switch r { - case '{': - if stop := p.stop - size; stop > p.start { - tmpl.exprs = append(tmpl.exprs, literals(p.r[p.start:stop])) - } - exp = &expression{} - tmpl.exprs = append(tmpl.exprs, exp) - p.setState(parseStateOperator) - case '%': - p.unread(r) - if err := p.consumeTriplet(); err != nil { - return nil, err - } - default: - if !unicode.Is(rangeLiterals, r) { - p.unread(r) - return nil, p.errorf('_', "unacceptable character (hint: use %%XX encoding)") - } - } - case parseStateOperator: - switch r { - default: - p.unread(r) - exp.op = parseOpSimple - case '+': - exp.op = parseOpPlus - case '#': - exp.op = parseOpCrosshatch - case '.': - exp.op = parseOpDot - case '/': - exp.op = parseOpSlash - case ';': - exp.op = parseOpSemicolon - case '?': - exp.op = parseOpQuestion - case '&': - exp.op = parseOpAmpersand - case '=', ',', '!', '@', '|': // op-reserved - return nil, p.errorf('|', "unimplemented operator (op-reserved)") - } - p.setState(parseStateVarName) - case parseStateVarList: - switch r { - case ',': - p.setState(parseStateVarName) - case '}': - exp.init() - p.setState(parseStateDefault) - default: - p.unread(r) - return nil, p.errorf('_', "unrecognized value modifier") - } - case parseStateVarName: - switch r { - case ':', '*': - name := p.r[p.start : p.stop-size] - if !isValidVarname(name) { - return nil, p.errorf('|', "unacceptable variable name") - } - explode := r == '*' - exp.vars = append(exp.vars, varspec{ - name: name, - explode: explode, - }) - if explode { - p.setState(parseStateVarList) - } else { - p.setState(parseStatePrefix) - } - case ',', '}': - p.unread(r) - name := p.r[p.start:p.stop] - if !isValidVarname(name) { - return nil, p.errorf('|', "unacceptable variable name") - } - exp.vars = append(exp.vars, varspec{ - name: name, - }) - p.setState(parseStateVarList) - case '%': - p.unread(r) - if err := p.consumeTriplet(); err != nil { - return nil, err - } - case '.': - if dot := p.stop - size; dot == p.start || p.r[dot-1] == '.' { - return nil, p.errorf('|', "unacceptable variable name") - } - default: - if !unicode.Is(rangeVarchar, r) { - p.unread(r) - return nil, p.errorf('_', "unacceptable variable name") - } - } - case parseStatePrefix: - spec := &(exp.vars[len(exp.vars)-1]) - switch { - case '0' <= r && r <= '9': - spec.maxlen *= 10 - spec.maxlen += int(r - '0') - if spec.maxlen == 0 || spec.maxlen > 9999 { - return nil, p.errorf('|', "max-length must be (0, 9999]") - } - default: - p.unread(r) - if spec.maxlen == 0 { - return nil, p.errorf('_', "max-length must be (0, 9999]") - } - p.setState(parseStateVarList) - } - default: - p.unread(r) - panic(p.errorf('_', "unhandled parseState(%d)", p.state)) - } - } -} - -func isValidVarname(name string) bool { - if l := len(name); l == 0 || name[0] == '.' || name[l-1] == '.' { - return false - } - for i := 1; i < len(name)-1; i++ { - switch c := name[i]; c { - case '.': - if name[i-1] == '.' { - return false - } - } - } - return true -} - -func (p *parser) consumeTriplet() error { - if len(p.r)-p.stop < 3 || p.r[p.stop] != '%' || !ishex(p.r[p.stop+1]) || !ishex(p.r[p.stop+2]) { - return p.errorf('_', "incomplete pct-encodeed") - } - p.stop += 3 - return nil -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/prog.go b/vendor/github.com/yosida95/uritemplate/v3/prog.go deleted file mode 100644 index 97af4f0eab..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/prog.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "bytes" - "strconv" -) - -type progOpcode uint16 - -const ( - // match - opRune progOpcode = iota - opRuneClass - opLineBegin - opLineEnd - // capture - opCapStart - opCapEnd - // stack - opSplit - opJmp - opJmpIfNotDefined - opJmpIfNotEmpty - opJmpIfNotFirst - // result - opEnd - // fake - opNoop - opcodeMax -) - -var opcodeNames = []string{ - // match - "opRune", - "opRuneClass", - "opLineBegin", - "opLineEnd", - // capture - "opCapStart", - "opCapEnd", - // stack - "opSplit", - "opJmp", - "opJmpIfNotDefined", - "opJmpIfNotEmpty", - "opJmpIfNotFirst", - // result - "opEnd", -} - -func (code progOpcode) String() string { - if code >= opcodeMax { - return "" - } - return opcodeNames[code] -} - -type progOp struct { - code progOpcode - r rune - rc runeClass - i uint32 - - name string -} - -func dumpProgOp(b *bytes.Buffer, op *progOp) { - b.WriteString(op.code.String()) - switch op.code { - case opRune: - b.WriteString("(") - b.WriteString(strconv.QuoteToASCII(string(op.r))) - b.WriteString(")") - case opRuneClass: - b.WriteString("(") - b.WriteString(op.rc.String()) - b.WriteString(")") - case opCapStart, opCapEnd: - b.WriteString("(") - b.WriteString(strconv.QuoteToASCII(op.name)) - b.WriteString(")") - case opSplit: - b.WriteString(" -> ") - b.WriteString(strconv.FormatInt(int64(op.i), 10)) - case opJmp, opJmpIfNotFirst: - b.WriteString(" -> ") - b.WriteString(strconv.FormatInt(int64(op.i), 10)) - case opJmpIfNotDefined, opJmpIfNotEmpty: - b.WriteString("(") - b.WriteString(strconv.QuoteToASCII(op.name)) - b.WriteString(")") - b.WriteString(" -> ") - b.WriteString(strconv.FormatInt(int64(op.i), 10)) - } -} - -type prog struct { - op []progOp - numCap int -} - -func dumpProg(b *bytes.Buffer, prog *prog, pc uint32) { - for i := range prog.op { - op := prog.op[i] - - pos := strconv.Itoa(i) - if uint32(i) == pc { - pos = "*" + pos - } - b.WriteString(" "[len(pos):]) - b.WriteString(pos) - - b.WriteByte('\t') - dumpProgOp(b, &op) - - b.WriteByte('\n') - } -} - -func (p *prog) String() string { - b := bytes.Buffer{} - dumpProg(&b, p, 0) - return b.String() -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/uritemplate.go b/vendor/github.com/yosida95/uritemplate/v3/uritemplate.go deleted file mode 100644 index dbd2673753..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/uritemplate.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import ( - "log" - "regexp" - "strings" - "sync" -) - -var ( - debug = debugT(false) -) - -type debugT bool - -func (t debugT) Printf(format string, v ...interface{}) { - if t { - log.Printf(format, v...) - } -} - -// Template represents a URI Template. -type Template struct { - raw string - exprs []template - - // protects the rest of fields - mu sync.Mutex - varnames []string - re *regexp.Regexp - prog *prog -} - -// New parses and constructs a new Template instance based on the template. -// New returns an error if the template cannot be recognized. -func New(template string) (*Template, error) { - return (&parser{r: template}).parseURITemplate() -} - -// MustNew panics if the template cannot be recognized. -func MustNew(template string) *Template { - ret, err := New(template) - if err != nil { - panic(err) - } - return ret -} - -// Raw returns a raw URI template passed to New in string. -func (t *Template) Raw() string { - return t.raw -} - -// Varnames returns variable names used in the template. -func (t *Template) Varnames() []string { - t.mu.Lock() - defer t.mu.Unlock() - if t.varnames != nil { - return t.varnames - } - - reg := map[string]struct{}{} - t.varnames = []string{} - for i := range t.exprs { - expr, ok := t.exprs[i].(*expression) - if !ok { - continue - } - for _, spec := range expr.vars { - if _, ok := reg[spec.name]; ok { - continue - } - reg[spec.name] = struct{}{} - t.varnames = append(t.varnames, spec.name) - } - } - - return t.varnames -} - -// Expand returns a URI reference corresponding to the template expanded using the passed variables. -func (t *Template) Expand(vars Values) (string, error) { - var w strings.Builder - for i := range t.exprs { - expr := t.exprs[i] - if err := expr.expand(&w, vars); err != nil { - return w.String(), err - } - } - return w.String(), nil -} - -// Regexp converts the template to regexp and returns compiled *regexp.Regexp. -func (t *Template) Regexp() *regexp.Regexp { - t.mu.Lock() - defer t.mu.Unlock() - if t.re != nil { - return t.re - } - - var b strings.Builder - b.WriteByte('^') - for _, expr := range t.exprs { - expr.regexp(&b) - } - b.WriteByte('$') - t.re = regexp.MustCompile(b.String()) - - return t.re -} diff --git a/vendor/github.com/yosida95/uritemplate/v3/value.go b/vendor/github.com/yosida95/uritemplate/v3/value.go deleted file mode 100644 index 0550eabdbf..0000000000 --- a/vendor/github.com/yosida95/uritemplate/v3/value.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (C) 2016 Kohei YOSHIDA. All rights reserved. -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of The BSD 3-Clause License -// that can be found in the LICENSE file. - -package uritemplate - -import "strings" - -// A varname containing pct-encoded characters is not the same variable as -// a varname with those same characters decoded. -// -// -- https://tools.ietf.org/html/rfc6570#section-2.3 -type Values map[string]Value - -func (v Values) Set(name string, value Value) { - v[name] = value -} - -func (v Values) Get(name string) Value { - if v == nil { - return Value{} - } - return v[name] -} - -type ValueType uint8 - -const ( - ValueTypeString = iota - ValueTypeList - ValueTypeKV - valueTypeLast -) - -var valueTypeNames = []string{ - "String", - "List", - "KV", -} - -func (vt ValueType) String() string { - if vt < valueTypeLast { - return valueTypeNames[vt] - } - return "" -} - -type Value struct { - T ValueType - V []string -} - -func (v Value) String() string { - if v.Valid() && v.T == ValueTypeString { - return v.V[0] - } - return "" -} - -func (v Value) List() []string { - if v.Valid() && v.T == ValueTypeList { - return v.V - } - return nil -} - -func (v Value) KV() []string { - if v.Valid() && v.T == ValueTypeKV { - return v.V - } - return nil -} - -func (v Value) Valid() bool { - switch v.T { - default: - return false - case ValueTypeString: - return len(v.V) > 0 - case ValueTypeList: - return len(v.V) > 0 - case ValueTypeKV: - return len(v.V) > 0 && len(v.V)%2 == 0 - } -} - -func (v Value) expand(w *strings.Builder, spec varspec, exp *expression) error { - switch v.T { - case ValueTypeString: - val := v.V[0] - var maxlen int - if max := len(val); spec.maxlen < 1 || spec.maxlen > max { - maxlen = max - } else { - maxlen = spec.maxlen - } - - if exp.named { - w.WriteString(spec.name) - if val == "" { - w.WriteString(exp.ifemp) - return nil - } - w.WriteByte('=') - } - return exp.escape(w, val[:maxlen]) - case ValueTypeList: - var sep string - if spec.explode { - sep = exp.sep - } else { - sep = "," - } - - var pre string - var preifemp string - if spec.explode && exp.named { - pre = spec.name + "=" - preifemp = spec.name + exp.ifemp - } - - if !spec.explode && exp.named { - w.WriteString(spec.name) - w.WriteByte('=') - } - for i := range v.V { - val := v.V[i] - if i > 0 { - w.WriteString(sep) - } - if val == "" { - w.WriteString(preifemp) - continue - } - w.WriteString(pre) - - if err := exp.escape(w, val); err != nil { - return err - } - } - case ValueTypeKV: - var sep string - var kvsep string - if spec.explode { - sep = exp.sep - kvsep = "=" - } else { - sep = "," - kvsep = "," - } - - var ifemp string - var kescape escapeFunc - if spec.explode && exp.named { - ifemp = exp.ifemp - kescape = escapeLiteral - } else { - ifemp = "," - kescape = exp.escape - } - - if !spec.explode && exp.named { - w.WriteString(spec.name) - w.WriteByte('=') - } - - for i := 0; i < len(v.V); i += 2 { - if i > 0 { - w.WriteString(sep) - } - if err := kescape(w, v.V[i]); err != nil { - return err - } - if v.V[i+1] == "" { - w.WriteString(ifemp) - continue - } - w.WriteString(kvsep) - - if err := exp.escape(w, v.V[i+1]); err != nil { - return err - } - } - } - return nil -} - -// String returns Value that represents string. -func String(v string) Value { - return Value{ - T: ValueTypeString, - V: []string{v}, - } -} - -// List returns Value that represents list. -func List(v ...string) Value { - return Value{ - T: ValueTypeList, - V: v, - } -} - -// KV returns Value that represents associative list. -// KV panics if len(kv) is not even. -func KV(kv ...string) Value { - if len(kv)%2 != 0 { - panic("uritemplate.go: count of the kv must be even number") - } - return Value{ - T: ValueTypeKV, - V: kv, - } -} diff --git a/vendor/golang.org/x/crypto/acme/jws.go b/vendor/golang.org/x/crypto/acme/jws.go index b38828d859..6850275665 100644 --- a/vendor/golang.org/x/crypto/acme/jws.go +++ b/vendor/golang.org/x/crypto/acme/jws.go @@ -92,7 +92,7 @@ func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, ur if err != nil { return nil, err } - phead := base64.RawURLEncoding.EncodeToString([]byte(phJSON)) + phead := base64.RawURLEncoding.EncodeToString(phJSON) var payload string if val, ok := claimset.(string); ok { payload = val diff --git a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go index bd896bdc76..8d99551fee 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go +++ b/vendor/golang.org/x/crypto/internal/poly1305/mac_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build (!amd64 && !ppc64le && !ppc64 && !s390x) || !gc || purego +//go:build (!amd64 && !loong64 && !ppc64le && !ppc64 && !s390x) || !gc || purego package poly1305 diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go similarity index 94% rename from vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go rename to vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go index 164cd47d32..315b84ac39 100644 --- a/vendor/golang.org/x/crypto/internal/poly1305/sum_amd64.go +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_asm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build gc && !purego +//go:build gc && !purego && (amd64 || loong64 || ppc64 || ppc64le) package poly1305 diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_loong64.s b/vendor/golang.org/x/crypto/internal/poly1305/sum_loong64.s new file mode 100644 index 0000000000..bc8361da40 --- /dev/null +++ b/vendor/golang.org/x/crypto/internal/poly1305/sum_loong64.s @@ -0,0 +1,123 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build gc && !purego + +// func update(state *macState, msg []byte) +TEXT ·update(SB), $0-32 + MOVV state+0(FP), R4 + MOVV msg_base+8(FP), R5 + MOVV msg_len+16(FP), R6 + + MOVV $0x10, R7 + + MOVV (R4), R8 // h0 + MOVV 8(R4), R9 // h1 + MOVV 16(R4), R10 // h2 + MOVV 24(R4), R11 // r0 + MOVV 32(R4), R12 // r1 + + BLT R6, R7, bytes_between_0_and_15 + +loop: + MOVV (R5), R14 // msg[0:8] + MOVV 8(R5), R16 // msg[8:16] + ADDV R14, R8, R8 // h0 (x1 + y1 = z1', if z1' < x1 then z1' overflow) + ADDV R16, R9, R27 + SGTU R14, R8, R24 // h0.carry + SGTU R9, R27, R28 + ADDV R27, R24, R9 // h1 + SGTU R27, R9, R24 + OR R24, R28, R24 // h1.carry + ADDV $0x01, R24, R24 + ADDV R10, R24, R10 // h2 + + ADDV $16, R5, R5 // msg = msg[16:] + +multiply: + MULV R8, R11, R14 // h0r0.lo + MULHVU R8, R11, R15 // h0r0.hi + MULV R9, R11, R13 // h1r0.lo + MULHVU R9, R11, R16 // h1r0.hi + ADDV R13, R15, R15 + SGTU R13, R15, R24 + ADDV R24, R16, R16 + MULV R10, R11, R25 + ADDV R16, R25, R25 + MULV R8, R12, R13 // h0r1.lo + MULHVU R8, R12, R16 // h0r1.hi + ADDV R13, R15, R15 + SGTU R13, R15, R24 + ADDV R24, R16, R16 + MOVV R16, R8 + MULV R10, R12, R26 // h2r1 + MULV R9, R12, R13 // h1r1.lo + MULHVU R9, R12, R16 // h1r1.hi + ADDV R13, R25, R25 + ADDV R16, R26, R27 + SGTU R13, R25, R24 + ADDV R27, R24, R26 + ADDV R8, R25, R25 + SGTU R8, R25, R24 + ADDV R24, R26, R26 + AND $3, R25, R10 + AND $-4, R25, R17 + ADDV R17, R14, R8 + ADDV R26, R15, R27 + SGTU R17, R8, R24 + SGTU R26, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R24, R10, R10 + SLLV $62, R26, R27 + SRLV $2, R25, R28 + SRLV $2, R26, R26 + OR R27, R28, R25 + ADDV R25, R8, R8 + ADDV R26, R9, R27 + SGTU R25, R8, R24 + SGTU R26, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R24, R10, R10 + + SUBV $16, R6, R6 + BGE R6, R7, loop + +bytes_between_0_and_15: + BEQ R6, R0, done + MOVV $1, R14 + XOR R15, R15 + ADDV R6, R5, R5 + +flush_buffer: + MOVBU -1(R5), R25 + SRLV $56, R14, R24 + SLLV $8, R15, R28 + SLLV $8, R14, R14 + OR R24, R28, R15 + XOR R25, R14, R14 + SUBV $1, R6, R6 + SUBV $1, R5, R5 + BNE R6, R0, flush_buffer + + ADDV R14, R8, R8 + SGTU R14, R8, R24 + ADDV R15, R9, R27 + SGTU R15, R27, R28 + ADDV R27, R24, R9 + SGTU R27, R9, R24 + OR R24, R28, R24 + ADDV R10, R24, R10 + + MOVV $16, R6 + JMP multiply + +done: + MOVV R8, (R4) + MOVV R9, 8(R4) + MOVV R10, 16(R4) + RET diff --git a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go b/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go deleted file mode 100644 index 1a1679aaad..0000000000 --- a/vendor/golang.org/x/crypto/internal/poly1305/sum_ppc64x.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2019 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build gc && !purego && (ppc64 || ppc64le) - -package poly1305 - -//go:noescape -func update(state *macState, msg []byte) - -// mac is a wrapper for macGeneric that redirects calls that would have gone to -// updateGeneric to update. -// -// Its Write and Sum methods are otherwise identical to the macGeneric ones, but -// using function pointers would carry a major performance cost. -type mac struct{ macGeneric } - -func (h *mac) Write(p []byte) (int, error) { - nn := len(p) - if h.offset > 0 { - n := copy(h.buffer[h.offset:], p) - if h.offset+n < TagSize { - h.offset += n - return nn, nil - } - p = p[n:] - h.offset = 0 - update(&h.macState, h.buffer[:]) - } - if n := len(p) - (len(p) % TagSize); n > 0 { - update(&h.macState, p[:n]) - p = p[n:] - } - if len(p) > 0 { - h.offset += copy(h.buffer[h.offset:], p) - } - return nn, nil -} - -func (h *mac) Sum(out *[16]byte) { - state := h.macState - if h.offset > 0 { - update(&state, h.buffer[:h.offset]) - } - finalize(out, &state.h, &state.s) -} diff --git a/vendor/golang.org/x/crypto/openpgp/armor/armor.go b/vendor/golang.org/x/crypto/openpgp/armor/armor.go new file mode 100644 index 0000000000..e664d127cb --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/armor/armor.go @@ -0,0 +1,233 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is +// very similar to PEM except that it has an additional CRC checksum. +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package armor + +import ( + "bufio" + "bytes" + "encoding/base64" + "io" + + "golang.org/x/crypto/openpgp/errors" +) + +// A Block represents an OpenPGP armored structure. +// +// The encoded form is: +// +// -----BEGIN Type----- +// Headers +// +// base64-encoded Bytes +// '=' base64 encoded checksum +// -----END Type----- +// +// where Headers is a possibly empty sequence of Key: Value lines. +// +// Since the armored data can be very large, this package presents a streaming +// interface. +type Block struct { + Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE"). + Header map[string]string // Optional headers. + Body io.Reader // A Reader from which the contents can be read + lReader lineReader + oReader openpgpReader +} + +var ArmorCorrupt error = errors.StructuralError("armor invalid") + +const crc24Init = 0xb704ce +const crc24Poly = 0x1864cfb +const crc24Mask = 0xffffff + +// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1 +func crc24(crc uint32, d []byte) uint32 { + for _, b := range d { + crc ^= uint32(b) << 16 + for i := 0; i < 8; i++ { + crc <<= 1 + if crc&0x1000000 != 0 { + crc ^= crc24Poly + } + } + } + return crc +} + +var armorStart = []byte("-----BEGIN ") +var armorEnd = []byte("-----END ") +var armorEndOfLine = []byte("-----") + +// lineReader wraps a line based reader. It watches for the end of an armor +// block and records the expected CRC value. +type lineReader struct { + in *bufio.Reader + buf []byte + eof bool + crc uint32 + crcSet bool +} + +func (l *lineReader) Read(p []byte) (n int, err error) { + if l.eof { + return 0, io.EOF + } + + if len(l.buf) > 0 { + n = copy(p, l.buf) + l.buf = l.buf[n:] + return + } + + line, isPrefix, err := l.in.ReadLine() + if err != nil { + return + } + if isPrefix { + return 0, ArmorCorrupt + } + + if bytes.HasPrefix(line, armorEnd) { + l.eof = true + return 0, io.EOF + } + + if len(line) == 5 && line[0] == '=' { + // This is the checksum line + var expectedBytes [3]byte + var m int + m, err = base64.StdEncoding.Decode(expectedBytes[0:], line[1:]) + if m != 3 || err != nil { + return + } + l.crc = uint32(expectedBytes[0])<<16 | + uint32(expectedBytes[1])<<8 | + uint32(expectedBytes[2]) + + line, _, err = l.in.ReadLine() + if err != nil && err != io.EOF { + return + } + if !bytes.HasPrefix(line, armorEnd) { + return 0, ArmorCorrupt + } + + l.eof = true + l.crcSet = true + return 0, io.EOF + } + + if len(line) > 96 { + return 0, ArmorCorrupt + } + + n = copy(p, line) + bytesToSave := len(line) - n + if bytesToSave > 0 { + if cap(l.buf) < bytesToSave { + l.buf = make([]byte, 0, bytesToSave) + } + l.buf = l.buf[0:bytesToSave] + copy(l.buf, line[n:]) + } + + return +} + +// openpgpReader passes Read calls to the underlying base64 decoder, but keeps +// a running CRC of the resulting data and checks the CRC against the value +// found by the lineReader at EOF. +type openpgpReader struct { + lReader *lineReader + b64Reader io.Reader + currentCRC uint32 +} + +func (r *openpgpReader) Read(p []byte) (n int, err error) { + n, err = r.b64Reader.Read(p) + r.currentCRC = crc24(r.currentCRC, p[:n]) + + if err == io.EOF && r.lReader.crcSet && r.lReader.crc != r.currentCRC&crc24Mask { + return 0, ArmorCorrupt + } + + return +} + +// Decode reads a PGP armored block from the given Reader. It will ignore +// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The +// given Reader is not usable after calling this function: an arbitrary amount +// of data may have been read past the end of the block. +func Decode(in io.Reader) (p *Block, err error) { + r := bufio.NewReaderSize(in, 100) + var line []byte + ignoreNext := false + +TryNextBlock: + p = nil + + // Skip leading garbage + for { + ignoreThis := ignoreNext + line, ignoreNext, err = r.ReadLine() + if err != nil { + return + } + if ignoreNext || ignoreThis { + continue + } + line = bytes.TrimSpace(line) + if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) { + break + } + } + + p = new(Block) + p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)]) + p.Header = make(map[string]string) + nextIsContinuation := false + var lastKey string + + // Read headers + for { + isContinuation := nextIsContinuation + line, nextIsContinuation, err = r.ReadLine() + if err != nil { + p = nil + return + } + if isContinuation { + p.Header[lastKey] += string(line) + continue + } + line = bytes.TrimSpace(line) + if len(line) == 0 { + break + } + + i := bytes.Index(line, []byte(": ")) + if i == -1 { + goto TryNextBlock + } + lastKey = string(line[:i]) + p.Header[lastKey] = string(line[i+2:]) + } + + p.lReader.in = r + p.oReader.currentCRC = crc24Init + p.oReader.lReader = &p.lReader + p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader) + p.Body = &p.oReader + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/armor/encode.go b/vendor/golang.org/x/crypto/openpgp/armor/encode.go new file mode 100644 index 0000000000..5b6e16c19d --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/armor/encode.go @@ -0,0 +1,161 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package armor + +import ( + "encoding/base64" + "io" +) + +var armorHeaderSep = []byte(": ") +var blockEnd = []byte("\n=") +var newline = []byte("\n") +var armorEndOfLineOut = []byte("-----\n") + +// writeSlices writes its arguments to the given Writer. +func writeSlices(out io.Writer, slices ...[]byte) (err error) { + for _, s := range slices { + _, err = out.Write(s) + if err != nil { + return err + } + } + return +} + +// lineBreaker breaks data across several lines, all of the same byte length +// (except possibly the last). Lines are broken with a single '\n'. +type lineBreaker struct { + lineLength int + line []byte + used int + out io.Writer + haveWritten bool +} + +func newLineBreaker(out io.Writer, lineLength int) *lineBreaker { + return &lineBreaker{ + lineLength: lineLength, + line: make([]byte, lineLength), + used: 0, + out: out, + } +} + +func (l *lineBreaker) Write(b []byte) (n int, err error) { + n = len(b) + + if n == 0 { + return + } + + if l.used == 0 && l.haveWritten { + _, err = l.out.Write([]byte{'\n'}) + if err != nil { + return + } + } + + if l.used+len(b) < l.lineLength { + l.used += copy(l.line[l.used:], b) + return + } + + l.haveWritten = true + _, err = l.out.Write(l.line[0:l.used]) + if err != nil { + return + } + excess := l.lineLength - l.used + l.used = 0 + + _, err = l.out.Write(b[0:excess]) + if err != nil { + return + } + + _, err = l.Write(b[excess:]) + return +} + +func (l *lineBreaker) Close() (err error) { + if l.used > 0 { + _, err = l.out.Write(l.line[0:l.used]) + if err != nil { + return + } + } + + return +} + +// encoding keeps track of a running CRC24 over the data which has been written +// to it and outputs a OpenPGP checksum when closed, followed by an armor +// trailer. +// +// It's built into a stack of io.Writers: +// +// encoding -> base64 encoder -> lineBreaker -> out +type encoding struct { + out io.Writer + breaker *lineBreaker + b64 io.WriteCloser + crc uint32 + blockType []byte +} + +func (e *encoding) Write(data []byte) (n int, err error) { + e.crc = crc24(e.crc, data) + return e.b64.Write(data) +} + +func (e *encoding) Close() (err error) { + err = e.b64.Close() + if err != nil { + return + } + e.breaker.Close() + + var checksumBytes [3]byte + checksumBytes[0] = byte(e.crc >> 16) + checksumBytes[1] = byte(e.crc >> 8) + checksumBytes[2] = byte(e.crc) + + var b64ChecksumBytes [4]byte + base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:]) + + return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine) +} + +// Encode returns a WriteCloser which will encode the data written to it in +// OpenPGP armor. +func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) { + bType := []byte(blockType) + err = writeSlices(out, armorStart, bType, armorEndOfLineOut) + if err != nil { + return + } + + for k, v := range headers { + err = writeSlices(out, []byte(k), armorHeaderSep, []byte(v), newline) + if err != nil { + return + } + } + + _, err = out.Write(newline) + if err != nil { + return + } + + e := &encoding{ + out: out, + breaker: newLineBreaker(out, 64), + crc: crc24Init, + blockType: bType, + } + e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker) + return e, nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/canonical_text.go b/vendor/golang.org/x/crypto/openpgp/canonical_text.go new file mode 100644 index 0000000000..e601e389f1 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/canonical_text.go @@ -0,0 +1,59 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import "hash" + +// NewCanonicalTextHash reformats text written to it into the canonical +// form and then applies the hash h. See RFC 4880, section 5.2.1. +func NewCanonicalTextHash(h hash.Hash) hash.Hash { + return &canonicalTextHash{h, 0} +} + +type canonicalTextHash struct { + h hash.Hash + s int +} + +var newline = []byte{'\r', '\n'} + +func (cth *canonicalTextHash) Write(buf []byte) (int, error) { + start := 0 + + for i, c := range buf { + switch cth.s { + case 0: + if c == '\r' { + cth.s = 1 + } else if c == '\n' { + cth.h.Write(buf[start:i]) + cth.h.Write(newline) + start = i + 1 + } + case 1: + cth.s = 0 + } + } + + cth.h.Write(buf[start:]) + return len(buf), nil +} + +func (cth *canonicalTextHash) Sum(in []byte) []byte { + return cth.h.Sum(in) +} + +func (cth *canonicalTextHash) Reset() { + cth.h.Reset() + cth.s = 0 +} + +func (cth *canonicalTextHash) Size() int { + return cth.h.Size() +} + +func (cth *canonicalTextHash) BlockSize() int { + return cth.h.BlockSize() +} diff --git a/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go new file mode 100644 index 0000000000..f922bdbcaa --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/elgamal/elgamal.go @@ -0,0 +1,130 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package elgamal implements ElGamal encryption, suitable for OpenPGP, +// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on +// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31, +// n. 4, 1985, pp. 469-472. +// +// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it +// unsuitable for other protocols. RSA should be used in preference in any +// case. +// +// Deprecated: this package was only provided to support ElGamal encryption in +// OpenPGP. The golang.org/x/crypto/openpgp package is now deprecated (see +// https://golang.org/issue/44226), and ElGamal in the OpenPGP ecosystem has +// compatibility and security issues (see https://eprint.iacr.org/2021/923). +// Moreover, this package doesn't protect against side-channel attacks. +package elgamal + +import ( + "crypto/rand" + "crypto/subtle" + "errors" + "io" + "math/big" +) + +// PublicKey represents an ElGamal public key. +type PublicKey struct { + G, P, Y *big.Int +} + +// PrivateKey represents an ElGamal private key. +type PrivateKey struct { + PublicKey + X *big.Int +} + +// Encrypt encrypts the given message to the given public key. The result is a +// pair of integers. Errors can result from reading random, or because msg is +// too large to be encrypted to the public key. +func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) { + pLen := (pub.P.BitLen() + 7) / 8 + if len(msg) > pLen-11 { + err = errors.New("elgamal: message too long") + return + } + + // EM = 0x02 || PS || 0x00 || M + em := make([]byte, pLen-1) + em[0] = 2 + ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):] + err = nonZeroRandomBytes(ps, random) + if err != nil { + return + } + em[len(em)-len(msg)-1] = 0 + copy(mm, msg) + + m := new(big.Int).SetBytes(em) + + k, err := rand.Int(random, pub.P) + if err != nil { + return + } + + c1 = new(big.Int).Exp(pub.G, k, pub.P) + s := new(big.Int).Exp(pub.Y, k, pub.P) + c2 = s.Mul(s, m) + c2.Mod(c2, pub.P) + + return +} + +// Decrypt takes two integers, resulting from an ElGamal encryption, and +// returns the plaintext of the message. An error can result only if the +// ciphertext is invalid. Users should keep in mind that this is a padding +// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can +// be used to break the cryptosystem. See “Chosen Ciphertext Attacks +// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel +// Bleichenbacher, Advances in Cryptology (Crypto '98), +func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) { + s := new(big.Int).Exp(c1, priv.X, priv.P) + if s.ModInverse(s, priv.P) == nil { + return nil, errors.New("elgamal: invalid private key") + } + s.Mul(s, c2) + s.Mod(s, priv.P) + em := s.Bytes() + + firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2) + + // The remainder of the plaintext must be a string of non-zero random + // octets, followed by a 0, followed by the message. + // lookingForIndex: 1 iff we are still looking for the zero. + // index: the offset of the first zero byte. + var lookingForIndex, index int + lookingForIndex = 1 + + for i := 1; i < len(em); i++ { + equals0 := subtle.ConstantTimeByteEq(em[i], 0) + index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index) + lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex) + } + + if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 { + return nil, errors.New("elgamal: decryption error") + } + return em[index+1:], nil +} + +// nonZeroRandomBytes fills the given slice with non-zero random octets. +func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) { + _, err = io.ReadFull(rand, s) + if err != nil { + return + } + + for i := 0; i < len(s); i++ { + for s[i] == 0 { + _, err = io.ReadFull(rand, s[i:i+1]) + if err != nil { + return + } + } + } + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/errors/errors.go b/vendor/golang.org/x/crypto/openpgp/errors/errors.go new file mode 100644 index 0000000000..a328749471 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/errors/errors.go @@ -0,0 +1,78 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package errors contains common error types for the OpenPGP packages. +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package errors + +import ( + "strconv" +) + +// A StructuralError is returned when OpenPGP data is found to be syntactically +// invalid. +type StructuralError string + +func (s StructuralError) Error() string { + return "openpgp: invalid data: " + string(s) +} + +// UnsupportedError indicates that, although the OpenPGP data is valid, it +// makes use of currently unimplemented features. +type UnsupportedError string + +func (s UnsupportedError) Error() string { + return "openpgp: unsupported feature: " + string(s) +} + +// InvalidArgumentError indicates that the caller is in error and passed an +// incorrect value. +type InvalidArgumentError string + +func (i InvalidArgumentError) Error() string { + return "openpgp: invalid argument: " + string(i) +} + +// SignatureError indicates that a syntactically valid signature failed to +// validate. +type SignatureError string + +func (b SignatureError) Error() string { + return "openpgp: invalid signature: " + string(b) +} + +type keyIncorrectError int + +func (ki keyIncorrectError) Error() string { + return "openpgp: incorrect key" +} + +var ErrKeyIncorrect error = keyIncorrectError(0) + +type unknownIssuerError int + +func (unknownIssuerError) Error() string { + return "openpgp: signature made by unknown entity" +} + +var ErrUnknownIssuer error = unknownIssuerError(0) + +type keyRevokedError int + +func (keyRevokedError) Error() string { + return "openpgp: signature made by revoked key" +} + +var ErrKeyRevoked error = keyRevokedError(0) + +type UnknownPacketTypeError uint8 + +func (upte UnknownPacketTypeError) Error() string { + return "openpgp: unknown packet type: " + strconv.Itoa(int(upte)) +} diff --git a/vendor/golang.org/x/crypto/openpgp/keys.go b/vendor/golang.org/x/crypto/openpgp/keys.go new file mode 100644 index 0000000000..d62f787e9d --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/keys.go @@ -0,0 +1,693 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import ( + "crypto/rsa" + "io" + "time" + + "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/packet" +) + +// PublicKeyType is the armor type for a PGP public key. +var PublicKeyType = "PGP PUBLIC KEY BLOCK" + +// PrivateKeyType is the armor type for a PGP private key. +var PrivateKeyType = "PGP PRIVATE KEY BLOCK" + +// An Entity represents the components of an OpenPGP key: a primary public key +// (which must be a signing key), one or more identities claimed by that key, +// and zero or more subkeys, which may be encryption keys. +type Entity struct { + PrimaryKey *packet.PublicKey + PrivateKey *packet.PrivateKey + Identities map[string]*Identity // indexed by Identity.Name + Revocations []*packet.Signature + Subkeys []Subkey +} + +// An Identity represents an identity claimed by an Entity and zero or more +// assertions by other entities about that claim. +type Identity struct { + Name string // by convention, has the form "Full Name (comment) " + UserId *packet.UserId + SelfSignature *packet.Signature + Signatures []*packet.Signature +} + +// A Subkey is an additional public key in an Entity. Subkeys can be used for +// encryption. +type Subkey struct { + PublicKey *packet.PublicKey + PrivateKey *packet.PrivateKey + Sig *packet.Signature +} + +// A Key identifies a specific public key in an Entity. This is either the +// Entity's primary key or a subkey. +type Key struct { + Entity *Entity + PublicKey *packet.PublicKey + PrivateKey *packet.PrivateKey + SelfSignature *packet.Signature +} + +// A KeyRing provides access to public and private keys. +type KeyRing interface { + // KeysById returns the set of keys that have the given key id. + KeysById(id uint64) []Key + // KeysByIdUsage returns the set of keys with the given id + // that also meet the key usage given by requiredUsage. + // The requiredUsage is expressed as the bitwise-OR of + // packet.KeyFlag* values. + KeysByIdUsage(id uint64, requiredUsage byte) []Key + // DecryptionKeys returns all private keys that are valid for + // decryption. + DecryptionKeys() []Key +} + +// primaryIdentity returns the Identity marked as primary or the first identity +// if none are so marked. +func (e *Entity) primaryIdentity() *Identity { + var firstIdentity *Identity + for _, ident := range e.Identities { + if firstIdentity == nil { + firstIdentity = ident + } + if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { + return ident + } + } + return firstIdentity +} + +// encryptionKey returns the best candidate Key for encrypting a message to the +// given Entity. +func (e *Entity) encryptionKey(now time.Time) (Key, bool) { + candidateSubkey := -1 + + // Iterate the keys to find the newest key + var maxTime time.Time + for i, subkey := range e.Subkeys { + if subkey.Sig.FlagsValid && + subkey.Sig.FlagEncryptCommunications && + subkey.PublicKey.PubKeyAlgo.CanEncrypt() && + !subkey.Sig.KeyExpired(now) && + (maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) { + candidateSubkey = i + maxTime = subkey.Sig.CreationTime + } + } + + if candidateSubkey != -1 { + subkey := e.Subkeys[candidateSubkey] + return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true + } + + // If we don't have any candidate subkeys for encryption and + // the primary key doesn't have any usage metadata then we + // assume that the primary key is ok. Or, if the primary key is + // marked as ok to encrypt to, then we can obviously use it. + i := e.primaryIdentity() + if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagEncryptCommunications && + e.PrimaryKey.PubKeyAlgo.CanEncrypt() && + !i.SelfSignature.KeyExpired(now) { + return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true + } + + // This Entity appears to be signing only. + return Key{}, false +} + +// signingKey return the best candidate Key for signing a message with this +// Entity. +func (e *Entity) signingKey(now time.Time) (Key, bool) { + candidateSubkey := -1 + + for i, subkey := range e.Subkeys { + if subkey.Sig.FlagsValid && + subkey.Sig.FlagSign && + subkey.PublicKey.PubKeyAlgo.CanSign() && + !subkey.Sig.KeyExpired(now) { + candidateSubkey = i + break + } + } + + if candidateSubkey != -1 { + subkey := e.Subkeys[candidateSubkey] + return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig}, true + } + + // If we have no candidate subkey then we assume that it's ok to sign + // with the primary key. + i := e.primaryIdentity() + if !i.SelfSignature.FlagsValid || i.SelfSignature.FlagSign && + !i.SelfSignature.KeyExpired(now) { + return Key{e, e.PrimaryKey, e.PrivateKey, i.SelfSignature}, true + } + + return Key{}, false +} + +// An EntityList contains one or more Entities. +type EntityList []*Entity + +// KeysById returns the set of keys that have the given key id. +func (el EntityList) KeysById(id uint64) (keys []Key) { + for _, e := range el { + if e.PrimaryKey.KeyId == id { + var selfSig *packet.Signature + for _, ident := range e.Identities { + if selfSig == nil { + selfSig = ident.SelfSignature + } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { + selfSig = ident.SelfSignature + break + } + } + keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig}) + } + + for _, subKey := range e.Subkeys { + if subKey.PublicKey.KeyId == id { + keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) + } + } + } + return +} + +// KeysByIdUsage returns the set of keys with the given id that also meet +// the key usage given by requiredUsage. The requiredUsage is expressed as +// the bitwise-OR of packet.KeyFlag* values. +func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) { + for _, key := range el.KeysById(id) { + if len(key.Entity.Revocations) > 0 { + continue + } + + if key.SelfSignature.RevocationReason != nil { + continue + } + + if key.SelfSignature.FlagsValid && requiredUsage != 0 { + var usage byte + if key.SelfSignature.FlagCertify { + usage |= packet.KeyFlagCertify + } + if key.SelfSignature.FlagSign { + usage |= packet.KeyFlagSign + } + if key.SelfSignature.FlagEncryptCommunications { + usage |= packet.KeyFlagEncryptCommunications + } + if key.SelfSignature.FlagEncryptStorage { + usage |= packet.KeyFlagEncryptStorage + } + if usage&requiredUsage != requiredUsage { + continue + } + } + + keys = append(keys, key) + } + return +} + +// DecryptionKeys returns all private keys that are valid for decryption. +func (el EntityList) DecryptionKeys() (keys []Key) { + for _, e := range el { + for _, subKey := range e.Subkeys { + if subKey.PrivateKey != nil && (!subKey.Sig.FlagsValid || subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) { + keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig}) + } + } + } + return +} + +// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file. +func ReadArmoredKeyRing(r io.Reader) (EntityList, error) { + block, err := armor.Decode(r) + if err == io.EOF { + return nil, errors.InvalidArgumentError("no armored data found") + } + if err != nil { + return nil, err + } + if block.Type != PublicKeyType && block.Type != PrivateKeyType { + return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type) + } + + return ReadKeyRing(block.Body) +} + +// ReadKeyRing reads one or more public/private keys. Unsupported keys are +// ignored as long as at least a single valid key is found. +func ReadKeyRing(r io.Reader) (el EntityList, err error) { + packets := packet.NewReader(r) + var lastUnsupportedError error + + for { + var e *Entity + e, err = ReadEntity(packets) + if err != nil { + // TODO: warn about skipped unsupported/unreadable keys + if _, ok := err.(errors.UnsupportedError); ok { + lastUnsupportedError = err + err = readToNextPublicKey(packets) + } else if _, ok := err.(errors.StructuralError); ok { + // Skip unreadable, badly-formatted keys + lastUnsupportedError = err + err = readToNextPublicKey(packets) + } + if err == io.EOF { + err = nil + break + } + if err != nil { + el = nil + break + } + } else { + el = append(el, e) + } + } + + if len(el) == 0 && err == nil { + err = lastUnsupportedError + } + return +} + +// readToNextPublicKey reads packets until the start of the entity and leaves +// the first packet of the new entity in the Reader. +func readToNextPublicKey(packets *packet.Reader) (err error) { + var p packet.Packet + for { + p, err = packets.Next() + if err == io.EOF { + return + } else if err != nil { + if _, ok := err.(errors.UnsupportedError); ok { + err = nil + continue + } + return + } + + if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey { + packets.Unread(p) + return + } + } +} + +// ReadEntity reads an entity (public key, identities, subkeys etc) from the +// given Reader. +func ReadEntity(packets *packet.Reader) (*Entity, error) { + e := new(Entity) + e.Identities = make(map[string]*Identity) + + p, err := packets.Next() + if err != nil { + return nil, err + } + + var ok bool + if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok { + if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok { + packets.Unread(p) + return nil, errors.StructuralError("first packet was not a public/private key") + } + e.PrimaryKey = &e.PrivateKey.PublicKey + } + + if !e.PrimaryKey.PubKeyAlgo.CanSign() { + return nil, errors.StructuralError("primary key cannot be used for signatures") + } + + var revocations []*packet.Signature +EachPacket: + for { + p, err := packets.Next() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + + switch pkt := p.(type) { + case *packet.UserId: + if err := addUserID(e, packets, pkt); err != nil { + return nil, err + } + case *packet.Signature: + if pkt.SigType == packet.SigTypeKeyRevocation { + revocations = append(revocations, pkt) + } else if pkt.SigType == packet.SigTypeDirectSignature { + // TODO: RFC4880 5.2.1 permits signatures + // directly on keys (eg. to bind additional + // revocation keys). + } + // Else, ignoring the signature as it does not follow anything + // we would know to attach it to. + case *packet.PrivateKey: + if pkt.IsSubkey == false { + packets.Unread(p) + break EachPacket + } + err = addSubkey(e, packets, &pkt.PublicKey, pkt) + if err != nil { + return nil, err + } + case *packet.PublicKey: + if pkt.IsSubkey == false { + packets.Unread(p) + break EachPacket + } + err = addSubkey(e, packets, pkt, nil) + if err != nil { + return nil, err + } + default: + // we ignore unknown packets + } + } + + if len(e.Identities) == 0 { + return nil, errors.StructuralError("entity without any identities") + } + + for _, revocation := range revocations { + err = e.PrimaryKey.VerifyRevocationSignature(revocation) + if err == nil { + e.Revocations = append(e.Revocations, revocation) + } else { + // TODO: RFC 4880 5.2.3.15 defines revocation keys. + return nil, errors.StructuralError("revocation signature signed by alternate key") + } + } + + return e, nil +} + +func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error { + // Make a new Identity object, that we might wind up throwing away. + // We'll only add it if we get a valid self-signature over this + // userID. + identity := new(Identity) + identity.Name = pkt.Id + identity.UserId = pkt + + for { + p, err := packets.Next() + if err == io.EOF { + break + } else if err != nil { + return err + } + + sig, ok := p.(*packet.Signature) + if !ok { + packets.Unread(p) + break + } + + if (sig.SigType == packet.SigTypePositiveCert || sig.SigType == packet.SigTypeGenericCert) && sig.IssuerKeyId != nil && *sig.IssuerKeyId == e.PrimaryKey.KeyId { + if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil { + return errors.StructuralError("user ID self-signature invalid: " + err.Error()) + } + identity.SelfSignature = sig + e.Identities[pkt.Id] = identity + } else { + identity.Signatures = append(identity.Signatures, sig) + } + } + + return nil +} + +func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error { + var subKey Subkey + subKey.PublicKey = pub + subKey.PrivateKey = priv + + for { + p, err := packets.Next() + if err == io.EOF { + break + } else if err != nil { + return errors.StructuralError("subkey signature invalid: " + err.Error()) + } + + sig, ok := p.(*packet.Signature) + if !ok { + packets.Unread(p) + break + } + + if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation { + return errors.StructuralError("subkey signature with wrong type") + } + + if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil { + return errors.StructuralError("subkey signature invalid: " + err.Error()) + } + + switch sig.SigType { + case packet.SigTypeSubkeyRevocation: + subKey.Sig = sig + case packet.SigTypeSubkeyBinding: + + if shouldReplaceSubkeySig(subKey.Sig, sig) { + subKey.Sig = sig + } + } + } + + if subKey.Sig == nil { + return errors.StructuralError("subkey packet not followed by signature") + } + + e.Subkeys = append(e.Subkeys, subKey) + + return nil +} + +func shouldReplaceSubkeySig(existingSig, potentialNewSig *packet.Signature) bool { + if potentialNewSig == nil { + return false + } + + if existingSig == nil { + return true + } + + if existingSig.SigType == packet.SigTypeSubkeyRevocation { + return false // never override a revocation signature + } + + return potentialNewSig.CreationTime.After(existingSig.CreationTime) +} + +const defaultRSAKeyBits = 2048 + +// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a +// single identity composed of the given full name, comment and email, any of +// which may be empty but must not contain any of "()<>\x00". +// If config is nil, sensible defaults will be used. +func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) { + creationTime := config.Now() + + bits := defaultRSAKeyBits + if config != nil && config.RSABits != 0 { + bits = config.RSABits + } + + uid := packet.NewUserId(name, comment, email) + if uid == nil { + return nil, errors.InvalidArgumentError("user id field contained invalid characters") + } + signingPriv, err := rsa.GenerateKey(config.Random(), bits) + if err != nil { + return nil, err + } + encryptingPriv, err := rsa.GenerateKey(config.Random(), bits) + if err != nil { + return nil, err + } + + e := &Entity{ + PrimaryKey: packet.NewRSAPublicKey(creationTime, &signingPriv.PublicKey), + PrivateKey: packet.NewRSAPrivateKey(creationTime, signingPriv), + Identities: make(map[string]*Identity), + } + isPrimaryId := true + e.Identities[uid.Id] = &Identity{ + Name: uid.Id, + UserId: uid, + SelfSignature: &packet.Signature{ + CreationTime: creationTime, + SigType: packet.SigTypePositiveCert, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + IsPrimaryId: &isPrimaryId, + FlagsValid: true, + FlagSign: true, + FlagCertify: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + } + err = e.Identities[uid.Id].SelfSignature.SignUserId(uid.Id, e.PrimaryKey, e.PrivateKey, config) + if err != nil { + return nil, err + } + + // If the user passes in a DefaultHash via packet.Config, + // set the PreferredHash for the SelfSignature. + if config != nil && config.DefaultHash != 0 { + e.Identities[uid.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(config.DefaultHash)} + } + + // Likewise for DefaultCipher. + if config != nil && config.DefaultCipher != 0 { + e.Identities[uid.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(config.DefaultCipher)} + } + + e.Subkeys = make([]Subkey, 1) + e.Subkeys[0] = Subkey{ + PublicKey: packet.NewRSAPublicKey(creationTime, &encryptingPriv.PublicKey), + PrivateKey: packet.NewRSAPrivateKey(creationTime, encryptingPriv), + Sig: &packet.Signature{ + CreationTime: creationTime, + SigType: packet.SigTypeSubkeyBinding, + PubKeyAlgo: packet.PubKeyAlgoRSA, + Hash: config.Hash(), + FlagsValid: true, + FlagEncryptStorage: true, + FlagEncryptCommunications: true, + IssuerKeyId: &e.PrimaryKey.KeyId, + }, + } + e.Subkeys[0].PublicKey.IsSubkey = true + e.Subkeys[0].PrivateKey.IsSubkey = true + err = e.Subkeys[0].Sig.SignKey(e.Subkeys[0].PublicKey, e.PrivateKey, config) + if err != nil { + return nil, err + } + return e, nil +} + +// SerializePrivate serializes an Entity, including private key material, but +// excluding signatures from other entities, to the given Writer. +// Identities and subkeys are re-signed in case they changed since NewEntry. +// If config is nil, sensible defaults will be used. +func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) { + err = e.PrivateKey.Serialize(w) + if err != nil { + return + } + for _, ident := range e.Identities { + err = ident.UserId.Serialize(w) + if err != nil { + return + } + err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config) + if err != nil { + return + } + err = ident.SelfSignature.Serialize(w) + if err != nil { + return + } + } + for _, subkey := range e.Subkeys { + err = subkey.PrivateKey.Serialize(w) + if err != nil { + return + } + err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config) + if err != nil { + return + } + err = subkey.Sig.Serialize(w) + if err != nil { + return + } + } + return nil +} + +// Serialize writes the public part of the given Entity to w, including +// signatures from other entities. No private key material will be output. +func (e *Entity) Serialize(w io.Writer) error { + err := e.PrimaryKey.Serialize(w) + if err != nil { + return err + } + for _, ident := range e.Identities { + err = ident.UserId.Serialize(w) + if err != nil { + return err + } + err = ident.SelfSignature.Serialize(w) + if err != nil { + return err + } + for _, sig := range ident.Signatures { + err = sig.Serialize(w) + if err != nil { + return err + } + } + } + for _, subkey := range e.Subkeys { + err = subkey.PublicKey.Serialize(w) + if err != nil { + return err + } + err = subkey.Sig.Serialize(w) + if err != nil { + return err + } + } + return nil +} + +// SignIdentity adds a signature to e, from signer, attesting that identity is +// associated with e. The provided identity must already be an element of +// e.Identities and the private key of signer must have been decrypted if +// necessary. +// If config is nil, sensible defaults will be used. +func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error { + if signer.PrivateKey == nil { + return errors.InvalidArgumentError("signing Entity must have a private key") + } + if signer.PrivateKey.Encrypted { + return errors.InvalidArgumentError("signing Entity's private key must be decrypted") + } + ident, ok := e.Identities[identity] + if !ok { + return errors.InvalidArgumentError("given identity string not found in Entity") + } + + sig := &packet.Signature{ + SigType: packet.SigTypeGenericCert, + PubKeyAlgo: signer.PrivateKey.PubKeyAlgo, + Hash: config.Hash(), + CreationTime: config.Now(), + IssuerKeyId: &signer.PrivateKey.KeyId, + } + if err := sig.SignUserId(identity, e.PrimaryKey, signer.PrivateKey, config); err != nil { + return err + } + ident.Signatures = append(ident.Signatures, sig) + return nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/compressed.go b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go new file mode 100644 index 0000000000..353f945247 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/compressed.go @@ -0,0 +1,123 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "compress/bzip2" + "compress/flate" + "compress/zlib" + "golang.org/x/crypto/openpgp/errors" + "io" + "strconv" +) + +// Compressed represents a compressed OpenPGP packet. The decompressed contents +// will contain more OpenPGP packets. See RFC 4880, section 5.6. +type Compressed struct { + Body io.Reader +} + +const ( + NoCompression = flate.NoCompression + BestSpeed = flate.BestSpeed + BestCompression = flate.BestCompression + DefaultCompression = flate.DefaultCompression +) + +// CompressionConfig contains compressor configuration settings. +type CompressionConfig struct { + // Level is the compression level to use. It must be set to + // between -1 and 9, with -1 causing the compressor to use the + // default compression level, 0 causing the compressor to use + // no compression and 1 to 9 representing increasing (better, + // slower) compression levels. If Level is less than -1 or + // more then 9, a non-nil error will be returned during + // encryption. See the constants above for convenient common + // settings for Level. + Level int +} + +func (c *Compressed) parse(r io.Reader) error { + var buf [1]byte + _, err := readFull(r, buf[:]) + if err != nil { + return err + } + + switch buf[0] { + case 1: + c.Body = flate.NewReader(r) + case 2: + c.Body, err = zlib.NewReader(r) + case 3: + c.Body = bzip2.NewReader(r) + default: + err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0]))) + } + + return err +} + +// compressedWriteCloser represents the serialized compression stream +// header and the compressor. Its Close() method ensures that both the +// compressor and serialized stream header are closed. Its Write() +// method writes to the compressor. +type compressedWriteCloser struct { + sh io.Closer // Stream Header + c io.WriteCloser // Compressor +} + +func (cwc compressedWriteCloser) Write(p []byte) (int, error) { + return cwc.c.Write(p) +} + +func (cwc compressedWriteCloser) Close() (err error) { + err = cwc.c.Close() + if err != nil { + return err + } + + return cwc.sh.Close() +} + +// SerializeCompressed serializes a compressed data packet to w and +// returns a WriteCloser to which the literal data packets themselves +// can be written and which MUST be closed on completion. If cc is +// nil, sensible defaults will be used to configure the compression +// algorithm. +func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) { + compressed, err := serializeStreamHeader(w, packetTypeCompressed) + if err != nil { + return + } + + _, err = compressed.Write([]byte{uint8(algo)}) + if err != nil { + return + } + + level := DefaultCompression + if cc != nil { + level = cc.Level + } + + var compressor io.WriteCloser + switch algo { + case CompressionZIP: + compressor, err = flate.NewWriter(compressed, level) + case CompressionZLIB: + compressor, err = zlib.NewWriterLevel(compressed, level) + default: + s := strconv.Itoa(int(algo)) + err = errors.UnsupportedError("Unsupported compression algorithm: " + s) + } + if err != nil { + return + } + + literaldata = compressedWriteCloser{compressed, compressor} + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/config.go b/vendor/golang.org/x/crypto/openpgp/packet/config.go new file mode 100644 index 0000000000..c76eecc963 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/config.go @@ -0,0 +1,91 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "crypto/rand" + "io" + "time" +) + +// Config collects a number of parameters along with sensible defaults. +// A nil *Config is valid and results in all default values. +type Config struct { + // Rand provides the source of entropy. + // If nil, the crypto/rand Reader is used. + Rand io.Reader + // DefaultHash is the default hash function to be used. + // If zero, SHA-256 is used. + DefaultHash crypto.Hash + // DefaultCipher is the cipher to be used. + // If zero, AES-128 is used. + DefaultCipher CipherFunction + // Time returns the current time as the number of seconds since the + // epoch. If Time is nil, time.Now is used. + Time func() time.Time + // DefaultCompressionAlgo is the compression algorithm to be + // applied to the plaintext before encryption. If zero, no + // compression is done. + DefaultCompressionAlgo CompressionAlgo + // CompressionConfig configures the compression settings. + CompressionConfig *CompressionConfig + // S2KCount is only used for symmetric encryption. It + // determines the strength of the passphrase stretching when + // the said passphrase is hashed to produce a key. S2KCount + // should be between 1024 and 65011712, inclusive. If Config + // is nil or S2KCount is 0, the value 65536 used. Not all + // values in the above range can be represented. S2KCount will + // be rounded up to the next representable value if it cannot + // be encoded exactly. When set, it is strongly encrouraged to + // use a value that is at least 65536. See RFC 4880 Section + // 3.7.1.3. + S2KCount int + // RSABits is the number of bits in new RSA keys made with NewEntity. + // If zero, then 2048 bit keys are created. + RSABits int +} + +func (c *Config) Random() io.Reader { + if c == nil || c.Rand == nil { + return rand.Reader + } + return c.Rand +} + +func (c *Config) Hash() crypto.Hash { + if c == nil || uint(c.DefaultHash) == 0 { + return crypto.SHA256 + } + return c.DefaultHash +} + +func (c *Config) Cipher() CipherFunction { + if c == nil || uint8(c.DefaultCipher) == 0 { + return CipherAES128 + } + return c.DefaultCipher +} + +func (c *Config) Now() time.Time { + if c == nil || c.Time == nil { + return time.Now() + } + return c.Time() +} + +func (c *Config) Compression() CompressionAlgo { + if c == nil { + return CompressionNone + } + return c.DefaultCompressionAlgo +} + +func (c *Config) PasswordHashIterations() int { + if c == nil || c.S2KCount == 0 { + return 0 + } + return c.S2KCount +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go new file mode 100644 index 0000000000..6d7639722c --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/encrypted_key.go @@ -0,0 +1,208 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "crypto/rsa" + "encoding/binary" + "io" + "math/big" + "strconv" + + "golang.org/x/crypto/openpgp/elgamal" + "golang.org/x/crypto/openpgp/errors" +) + +const encryptedKeyVersion = 3 + +// EncryptedKey represents a public-key encrypted session key. See RFC 4880, +// section 5.1. +type EncryptedKey struct { + KeyId uint64 + Algo PublicKeyAlgorithm + CipherFunc CipherFunction // only valid after a successful Decrypt + Key []byte // only valid after a successful Decrypt + + encryptedMPI1, encryptedMPI2 parsedMPI +} + +func (e *EncryptedKey) parse(r io.Reader) (err error) { + var buf [10]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != encryptedKeyVersion { + return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0]))) + } + e.KeyId = binary.BigEndian.Uint64(buf[1:9]) + e.Algo = PublicKeyAlgorithm(buf[9]) + switch e.Algo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) + if err != nil { + return + } + case PubKeyAlgoElGamal: + e.encryptedMPI1.bytes, e.encryptedMPI1.bitLength, err = readMPI(r) + if err != nil { + return + } + e.encryptedMPI2.bytes, e.encryptedMPI2.bitLength, err = readMPI(r) + if err != nil { + return + } + } + _, err = consumeAll(r) + return +} + +func checksumKeyMaterial(key []byte) uint16 { + var checksum uint16 + for _, v := range key { + checksum += uint16(v) + } + return checksum +} + +// Decrypt decrypts an encrypted session key with the given private key. The +// private key must have been decrypted first. +// If config is nil, sensible defaults will be used. +func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error { + var err error + var b []byte + + // TODO(agl): use session key decryption routines here to avoid + // padding oracle attacks. + switch priv.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + // Supports both *rsa.PrivateKey and crypto.Decrypter + k := priv.PrivateKey.(crypto.Decrypter) + b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.bytes), nil) + case PubKeyAlgoElGamal: + c1 := new(big.Int).SetBytes(e.encryptedMPI1.bytes) + c2 := new(big.Int).SetBytes(e.encryptedMPI2.bytes) + b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2) + default: + err = errors.InvalidArgumentError("cannot decrypted encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo))) + } + + if err != nil { + return err + } + + e.CipherFunc = CipherFunction(b[0]) + e.Key = b[1 : len(b)-2] + expectedChecksum := uint16(b[len(b)-2])<<8 | uint16(b[len(b)-1]) + checksum := checksumKeyMaterial(e.Key) + if checksum != expectedChecksum { + return errors.StructuralError("EncryptedKey checksum incorrect") + } + + return nil +} + +// Serialize writes the encrypted key packet, e, to w. +func (e *EncryptedKey) Serialize(w io.Writer) error { + var mpiLen int + switch e.Algo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + mpiLen = 2 + len(e.encryptedMPI1.bytes) + case PubKeyAlgoElGamal: + mpiLen = 2 + len(e.encryptedMPI1.bytes) + 2 + len(e.encryptedMPI2.bytes) + default: + return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo))) + } + + serializeHeader(w, packetTypeEncryptedKey, 1 /* version */ +8 /* key id */ +1 /* algo */ +mpiLen) + + w.Write([]byte{encryptedKeyVersion}) + binary.Write(w, binary.BigEndian, e.KeyId) + w.Write([]byte{byte(e.Algo)}) + + switch e.Algo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + writeMPIs(w, e.encryptedMPI1) + case PubKeyAlgoElGamal: + writeMPIs(w, e.encryptedMPI1, e.encryptedMPI2) + default: + panic("internal error") + } + + return nil +} + +// SerializeEncryptedKey serializes an encrypted key packet to w that contains +// key, encrypted to pub. +// If config is nil, sensible defaults will be used. +func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error { + var buf [10]byte + buf[0] = encryptedKeyVersion + binary.BigEndian.PutUint64(buf[1:9], pub.KeyId) + buf[9] = byte(pub.PubKeyAlgo) + + keyBlock := make([]byte, 1 /* cipher type */ +len(key)+2 /* checksum */) + keyBlock[0] = byte(cipherFunc) + copy(keyBlock[1:], key) + checksum := checksumKeyMaterial(key) + keyBlock[1+len(key)] = byte(checksum >> 8) + keyBlock[1+len(key)+1] = byte(checksum) + + switch pub.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly: + return serializeEncryptedKeyRSA(w, config.Random(), buf, pub.PublicKey.(*rsa.PublicKey), keyBlock) + case PubKeyAlgoElGamal: + return serializeEncryptedKeyElGamal(w, config.Random(), buf, pub.PublicKey.(*elgamal.PublicKey), keyBlock) + case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly: + return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) + } + + return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo))) +} + +func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header [10]byte, pub *rsa.PublicKey, keyBlock []byte) error { + cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock) + if err != nil { + return errors.InvalidArgumentError("RSA encryption failed: " + err.Error()) + } + + packetLen := 10 /* header length */ + 2 /* mpi size */ + len(cipherText) + + err = serializeHeader(w, packetTypeEncryptedKey, packetLen) + if err != nil { + return err + } + _, err = w.Write(header[:]) + if err != nil { + return err + } + return writeMPI(w, 8*uint16(len(cipherText)), cipherText) +} + +func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header [10]byte, pub *elgamal.PublicKey, keyBlock []byte) error { + c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock) + if err != nil { + return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error()) + } + + packetLen := 10 /* header length */ + packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8 + packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8 + + err = serializeHeader(w, packetTypeEncryptedKey, packetLen) + if err != nil { + return err + } + _, err = w.Write(header[:]) + if err != nil { + return err + } + err = writeBig(w, c1) + if err != nil { + return err + } + return writeBig(w, c2) +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/literal.go b/vendor/golang.org/x/crypto/openpgp/packet/literal.go new file mode 100644 index 0000000000..1a9ec6e51e --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/literal.go @@ -0,0 +1,89 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "encoding/binary" + "io" +) + +// LiteralData represents an encrypted file. See RFC 4880, section 5.9. +type LiteralData struct { + IsBinary bool + FileName string + Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined. + Body io.Reader +} + +// ForEyesOnly returns whether the contents of the LiteralData have been marked +// as especially sensitive. +func (l *LiteralData) ForEyesOnly() bool { + return l.FileName == "_CONSOLE" +} + +func (l *LiteralData) parse(r io.Reader) (err error) { + var buf [256]byte + + _, err = readFull(r, buf[:2]) + if err != nil { + return + } + + l.IsBinary = buf[0] == 'b' + fileNameLen := int(buf[1]) + + _, err = readFull(r, buf[:fileNameLen]) + if err != nil { + return + } + + l.FileName = string(buf[:fileNameLen]) + + _, err = readFull(r, buf[:4]) + if err != nil { + return + } + + l.Time = binary.BigEndian.Uint32(buf[:4]) + l.Body = r + return +} + +// SerializeLiteral serializes a literal data packet to w and returns a +// WriteCloser to which the data itself can be written and which MUST be closed +// on completion. The fileName is truncated to 255 bytes. +func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) { + var buf [4]byte + buf[0] = 't' + if isBinary { + buf[0] = 'b' + } + if len(fileName) > 255 { + fileName = fileName[:255] + } + buf[1] = byte(len(fileName)) + + inner, err := serializeStreamHeader(w, packetTypeLiteralData) + if err != nil { + return + } + + _, err = inner.Write(buf[:2]) + if err != nil { + return + } + _, err = inner.Write([]byte(fileName)) + if err != nil { + return + } + binary.BigEndian.PutUint32(buf[:], time) + _, err = inner.Write(buf[:]) + if err != nil { + return + } + + plaintext = inner + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go new file mode 100644 index 0000000000..ce2a33a547 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/ocfb.go @@ -0,0 +1,143 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9 + +package packet + +import ( + "crypto/cipher" +) + +type ocfbEncrypter struct { + b cipher.Block + fre []byte + outUsed int +} + +// An OCFBResyncOption determines if the "resynchronization step" of OCFB is +// performed. +type OCFBResyncOption bool + +const ( + OCFBResync OCFBResyncOption = true + OCFBNoResync OCFBResyncOption = false +) + +// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's +// cipher feedback mode using the given cipher.Block, and an initial amount of +// ciphertext. randData must be random bytes and be the same length as the +// cipher.Block's block size. Resync determines if the "resynchronization step" +// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on +// this point. +func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) { + blockSize := block.BlockSize() + if len(randData) != blockSize { + return nil, nil + } + + x := &ocfbEncrypter{ + b: block, + fre: make([]byte, blockSize), + outUsed: 0, + } + prefix := make([]byte, blockSize+2) + + block.Encrypt(x.fre, x.fre) + for i := 0; i < blockSize; i++ { + prefix[i] = randData[i] ^ x.fre[i] + } + + block.Encrypt(x.fre, prefix[:blockSize]) + prefix[blockSize] = x.fre[0] ^ randData[blockSize-2] + prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1] + + if resync { + block.Encrypt(x.fre, prefix[2:]) + } else { + x.fre[0] = prefix[blockSize] + x.fre[1] = prefix[blockSize+1] + x.outUsed = 2 + } + return x, prefix +} + +func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) { + for i := 0; i < len(src); i++ { + if x.outUsed == len(x.fre) { + x.b.Encrypt(x.fre, x.fre) + x.outUsed = 0 + } + + x.fre[x.outUsed] ^= src[i] + dst[i] = x.fre[x.outUsed] + x.outUsed++ + } +} + +type ocfbDecrypter struct { + b cipher.Block + fre []byte + outUsed int +} + +// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's +// cipher feedback mode using the given cipher.Block. Prefix must be the first +// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's +// block size. If an incorrect key is detected then nil is returned. On +// successful exit, blockSize+2 bytes of decrypted data are written into +// prefix. Resync determines if the "resynchronization step" from RFC 4880, +// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point. +func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream { + blockSize := block.BlockSize() + if len(prefix) != blockSize+2 { + return nil + } + + x := &ocfbDecrypter{ + b: block, + fre: make([]byte, blockSize), + outUsed: 0, + } + prefixCopy := make([]byte, len(prefix)) + copy(prefixCopy, prefix) + + block.Encrypt(x.fre, x.fre) + for i := 0; i < blockSize; i++ { + prefixCopy[i] ^= x.fre[i] + } + + block.Encrypt(x.fre, prefix[:blockSize]) + prefixCopy[blockSize] ^= x.fre[0] + prefixCopy[blockSize+1] ^= x.fre[1] + + if prefixCopy[blockSize-2] != prefixCopy[blockSize] || + prefixCopy[blockSize-1] != prefixCopy[blockSize+1] { + return nil + } + + if resync { + block.Encrypt(x.fre, prefix[2:]) + } else { + x.fre[0] = prefix[blockSize] + x.fre[1] = prefix[blockSize+1] + x.outUsed = 2 + } + copy(prefix, prefixCopy) + return x +} + +func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) { + for i := 0; i < len(src); i++ { + if x.outUsed == len(x.fre) { + x.b.Encrypt(x.fre, x.fre) + x.outUsed = 0 + } + + c := src[i] + dst[i] = x.fre[x.outUsed] ^ src[i] + x.fre[x.outUsed] = c + x.outUsed++ + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go new file mode 100644 index 0000000000..1713503395 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/one_pass_signature.go @@ -0,0 +1,73 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "encoding/binary" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" + "io" + "strconv" +) + +// OnePassSignature represents a one-pass signature packet. See RFC 4880, +// section 5.4. +type OnePassSignature struct { + SigType SignatureType + Hash crypto.Hash + PubKeyAlgo PublicKeyAlgorithm + KeyId uint64 + IsLast bool +} + +const onePassSignatureVersion = 3 + +func (ops *OnePassSignature) parse(r io.Reader) (err error) { + var buf [13]byte + + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != onePassSignatureVersion { + err = errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0]))) + } + + var ok bool + ops.Hash, ok = s2k.HashIdToHash(buf[2]) + if !ok { + return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2]))) + } + + ops.SigType = SignatureType(buf[1]) + ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3]) + ops.KeyId = binary.BigEndian.Uint64(buf[4:12]) + ops.IsLast = buf[12] != 0 + return +} + +// Serialize marshals the given OnePassSignature to w. +func (ops *OnePassSignature) Serialize(w io.Writer) error { + var buf [13]byte + buf[0] = onePassSignatureVersion + buf[1] = uint8(ops.SigType) + var ok bool + buf[2], ok = s2k.HashToHashId(ops.Hash) + if !ok { + return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash))) + } + buf[3] = uint8(ops.PubKeyAlgo) + binary.BigEndian.PutUint64(buf[4:12], ops.KeyId) + if ops.IsLast { + buf[12] = 1 + } + + if err := serializeHeader(w, packetTypeOnePassSignature, len(buf)); err != nil { + return err + } + _, err := w.Write(buf[:]) + return err +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/opaque.go b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go new file mode 100644 index 0000000000..3984477310 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/opaque.go @@ -0,0 +1,161 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "io" + + "golang.org/x/crypto/openpgp/errors" +) + +// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is +// useful for splitting and storing the original packet contents separately, +// handling unsupported packet types or accessing parts of the packet not yet +// implemented by this package. +type OpaquePacket struct { + // Packet type + Tag uint8 + // Reason why the packet was parsed opaquely + Reason error + // Binary contents of the packet data + Contents []byte +} + +func (op *OpaquePacket) parse(r io.Reader) (err error) { + op.Contents, err = io.ReadAll(r) + return +} + +// Serialize marshals the packet to a writer in its original form, including +// the packet header. +func (op *OpaquePacket) Serialize(w io.Writer) (err error) { + err = serializeHeader(w, packetType(op.Tag), len(op.Contents)) + if err == nil { + _, err = w.Write(op.Contents) + } + return +} + +// Parse attempts to parse the opaque contents into a structure supported by +// this package. If the packet is not known then the result will be another +// OpaquePacket. +func (op *OpaquePacket) Parse() (p Packet, err error) { + hdr := bytes.NewBuffer(nil) + err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents)) + if err != nil { + op.Reason = err + return op, err + } + p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents))) + if err != nil { + op.Reason = err + p = op + } + return +} + +// OpaqueReader reads OpaquePackets from an io.Reader. +type OpaqueReader struct { + r io.Reader +} + +func NewOpaqueReader(r io.Reader) *OpaqueReader { + return &OpaqueReader{r: r} +} + +// Read the next OpaquePacket. +func (or *OpaqueReader) Next() (op *OpaquePacket, err error) { + tag, _, contents, err := readHeader(or.r) + if err != nil { + return + } + op = &OpaquePacket{Tag: uint8(tag), Reason: err} + err = op.parse(contents) + if err != nil { + consumeAll(contents) + } + return +} + +// OpaqueSubpacket represents an unparsed OpenPGP subpacket, +// as found in signature and user attribute packets. +type OpaqueSubpacket struct { + SubType uint8 + Contents []byte +} + +// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from +// their byte representation. +func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) { + var ( + subHeaderLen int + subPacket *OpaqueSubpacket + ) + for len(contents) > 0 { + subHeaderLen, subPacket, err = nextSubpacket(contents) + if err != nil { + break + } + result = append(result, subPacket) + contents = contents[subHeaderLen+len(subPacket.Contents):] + } + return +} + +func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) { + // RFC 4880, section 5.2.3.1 + var subLen uint32 + if len(contents) < 1 { + goto Truncated + } + subPacket = &OpaqueSubpacket{} + switch { + case contents[0] < 192: + subHeaderLen = 2 // 1 length byte, 1 subtype byte + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[0]) + contents = contents[1:] + case contents[0] < 255: + subHeaderLen = 3 // 2 length bytes, 1 subtype + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192 + contents = contents[2:] + default: + subHeaderLen = 6 // 5 length bytes, 1 subtype + if len(contents) < subHeaderLen { + goto Truncated + } + subLen = uint32(contents[1])<<24 | + uint32(contents[2])<<16 | + uint32(contents[3])<<8 | + uint32(contents[4]) + contents = contents[5:] + } + if subLen > uint32(len(contents)) || subLen == 0 { + goto Truncated + } + subPacket.SubType = contents[0] + subPacket.Contents = contents[1:subLen] + return +Truncated: + err = errors.StructuralError("subpacket truncated") + return +} + +func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) { + buf := make([]byte, 6) + n := serializeSubpacketLength(buf, len(osp.Contents)+1) + buf[n] = osp.SubType + if _, err = w.Write(buf[:n+1]); err != nil { + return + } + _, err = w.Write(osp.Contents) + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/packet.go b/vendor/golang.org/x/crypto/openpgp/packet/packet.go new file mode 100644 index 0000000000..a84a1a214e --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/packet.go @@ -0,0 +1,590 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package packet implements parsing and serialization of OpenPGP packets, as +// specified in RFC 4880. +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package packet + +import ( + "bufio" + "crypto/aes" + "crypto/cipher" + "crypto/des" + "crypto/rsa" + "io" + "math/big" + "math/bits" + + "golang.org/x/crypto/cast5" + "golang.org/x/crypto/openpgp/errors" +) + +// readFull is the same as io.ReadFull except that reading zero bytes returns +// ErrUnexpectedEOF rather than EOF. +func readFull(r io.Reader, buf []byte) (n int, err error) { + n, err = io.ReadFull(r, buf) + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2. +func readLength(r io.Reader) (length int64, isPartial bool, err error) { + var buf [4]byte + _, err = readFull(r, buf[:1]) + if err != nil { + return + } + switch { + case buf[0] < 192: + length = int64(buf[0]) + case buf[0] < 224: + length = int64(buf[0]-192) << 8 + _, err = readFull(r, buf[0:1]) + if err != nil { + return + } + length += int64(buf[0]) + 192 + case buf[0] < 255: + length = int64(1) << (buf[0] & 0x1f) + isPartial = true + default: + _, err = readFull(r, buf[0:4]) + if err != nil { + return + } + length = int64(buf[0])<<24 | + int64(buf[1])<<16 | + int64(buf[2])<<8 | + int64(buf[3]) + } + return +} + +// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths. +// The continuation lengths are parsed and removed from the stream and EOF is +// returned at the end of the packet. See RFC 4880, section 4.2.2.4. +type partialLengthReader struct { + r io.Reader + remaining int64 + isPartial bool +} + +func (r *partialLengthReader) Read(p []byte) (n int, err error) { + for r.remaining == 0 { + if !r.isPartial { + return 0, io.EOF + } + r.remaining, r.isPartial, err = readLength(r.r) + if err != nil { + return 0, err + } + } + + toRead := int64(len(p)) + if toRead > r.remaining { + toRead = r.remaining + } + + n, err = r.r.Read(p[:int(toRead)]) + r.remaining -= int64(n) + if n < int(toRead) && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// partialLengthWriter writes a stream of data using OpenPGP partial lengths. +// See RFC 4880, section 4.2.2.4. +type partialLengthWriter struct { + w io.WriteCloser + lengthByte [1]byte + sentFirst bool + buf []byte +} + +// RFC 4880 4.2.2.4: the first partial length MUST be at least 512 octets long. +const minFirstPartialWrite = 512 + +func (w *partialLengthWriter) Write(p []byte) (n int, err error) { + off := 0 + if !w.sentFirst { + if len(w.buf) > 0 || len(p) < minFirstPartialWrite { + off = len(w.buf) + w.buf = append(w.buf, p...) + if len(w.buf) < minFirstPartialWrite { + return len(p), nil + } + p = w.buf + w.buf = nil + } + w.sentFirst = true + } + + power := uint8(30) + for len(p) > 0 { + l := 1 << power + if len(p) < l { + power = uint8(bits.Len32(uint32(len(p)))) - 1 + l = 1 << power + } + w.lengthByte[0] = 224 + power + _, err = w.w.Write(w.lengthByte[:]) + if err == nil { + var m int + m, err = w.w.Write(p[:l]) + n += m + } + if err != nil { + if n < off { + return 0, err + } + return n - off, err + } + p = p[l:] + } + return n - off, nil +} + +func (w *partialLengthWriter) Close() error { + if len(w.buf) > 0 { + // In this case we can't send a 512 byte packet. + // Just send what we have. + p := w.buf + w.sentFirst = true + w.buf = nil + if _, err := w.Write(p); err != nil { + return err + } + } + + w.lengthByte[0] = 0 + _, err := w.w.Write(w.lengthByte[:]) + if err != nil { + return err + } + return w.w.Close() +} + +// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the +// underlying Reader returns EOF before the limit has been reached. +type spanReader struct { + r io.Reader + n int64 +} + +func (l *spanReader) Read(p []byte) (n int, err error) { + if l.n <= 0 { + return 0, io.EOF + } + if int64(len(p)) > l.n { + p = p[0:l.n] + } + n, err = l.r.Read(p) + l.n -= int64(n) + if l.n > 0 && err == io.EOF { + err = io.ErrUnexpectedEOF + } + return +} + +// readHeader parses a packet header and returns an io.Reader which will return +// the contents of the packet. See RFC 4880, section 4.2. +func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) { + var buf [4]byte + _, err = io.ReadFull(r, buf[:1]) + if err != nil { + return + } + if buf[0]&0x80 == 0 { + err = errors.StructuralError("tag byte does not have MSB set") + return + } + if buf[0]&0x40 == 0 { + // Old format packet + tag = packetType((buf[0] & 0x3f) >> 2) + lengthType := buf[0] & 3 + if lengthType == 3 { + length = -1 + contents = r + return + } + lengthBytes := 1 << lengthType + _, err = readFull(r, buf[0:lengthBytes]) + if err != nil { + return + } + for i := 0; i < lengthBytes; i++ { + length <<= 8 + length |= int64(buf[i]) + } + contents = &spanReader{r, length} + return + } + + // New format packet + tag = packetType(buf[0] & 0x3f) + length, isPartial, err := readLength(r) + if err != nil { + return + } + if isPartial { + contents = &partialLengthReader{ + remaining: length, + isPartial: true, + r: r, + } + length = -1 + } else { + contents = &spanReader{r, length} + } + return +} + +// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section +// 4.2. +func serializeHeader(w io.Writer, ptype packetType, length int) (err error) { + var buf [6]byte + var n int + + buf[0] = 0x80 | 0x40 | byte(ptype) + if length < 192 { + buf[1] = byte(length) + n = 2 + } else if length < 8384 { + length -= 192 + buf[1] = 192 + byte(length>>8) + buf[2] = byte(length) + n = 3 + } else { + buf[1] = 255 + buf[2] = byte(length >> 24) + buf[3] = byte(length >> 16) + buf[4] = byte(length >> 8) + buf[5] = byte(length) + n = 6 + } + + _, err = w.Write(buf[:n]) + return +} + +// serializeStreamHeader writes an OpenPGP packet header to w where the +// length of the packet is unknown. It returns a io.WriteCloser which can be +// used to write the contents of the packet. See RFC 4880, section 4.2. +func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) { + var buf [1]byte + buf[0] = 0x80 | 0x40 | byte(ptype) + _, err = w.Write(buf[:]) + if err != nil { + return + } + out = &partialLengthWriter{w: w} + return +} + +// Packet represents an OpenPGP packet. Users are expected to try casting +// instances of this interface to specific packet types. +type Packet interface { + parse(io.Reader) error +} + +// consumeAll reads from the given Reader until error, returning the number of +// bytes read. +func consumeAll(r io.Reader) (n int64, err error) { + var m int + var buf [1024]byte + + for { + m, err = r.Read(buf[:]) + n += int64(m) + if err == io.EOF { + err = nil + return + } + if err != nil { + return + } + } +} + +// packetType represents the numeric ids of the different OpenPGP packet types. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2 +type packetType uint8 + +const ( + packetTypeEncryptedKey packetType = 1 + packetTypeSignature packetType = 2 + packetTypeSymmetricKeyEncrypted packetType = 3 + packetTypeOnePassSignature packetType = 4 + packetTypePrivateKey packetType = 5 + packetTypePublicKey packetType = 6 + packetTypePrivateSubkey packetType = 7 + packetTypeCompressed packetType = 8 + packetTypeSymmetricallyEncrypted packetType = 9 + packetTypeLiteralData packetType = 11 + packetTypeUserId packetType = 13 + packetTypePublicSubkey packetType = 14 + packetTypeUserAttribute packetType = 17 + packetTypeSymmetricallyEncryptedMDC packetType = 18 +) + +// peekVersion detects the version of a public key packet about to +// be read. A bufio.Reader at the original position of the io.Reader +// is returned. +func peekVersion(r io.Reader) (bufr *bufio.Reader, ver byte, err error) { + bufr = bufio.NewReader(r) + var verBuf []byte + if verBuf, err = bufr.Peek(1); err != nil { + return + } + ver = verBuf[0] + return +} + +// Read reads a single OpenPGP packet from the given io.Reader. If there is an +// error parsing a packet, the whole packet is consumed from the input. +func Read(r io.Reader) (p Packet, err error) { + tag, _, contents, err := readHeader(r) + if err != nil { + return + } + + switch tag { + case packetTypeEncryptedKey: + p = new(EncryptedKey) + case packetTypeSignature: + var version byte + // Detect signature version + if contents, version, err = peekVersion(contents); err != nil { + return + } + if version < 4 { + p = new(SignatureV3) + } else { + p = new(Signature) + } + case packetTypeSymmetricKeyEncrypted: + p = new(SymmetricKeyEncrypted) + case packetTypeOnePassSignature: + p = new(OnePassSignature) + case packetTypePrivateKey, packetTypePrivateSubkey: + pk := new(PrivateKey) + if tag == packetTypePrivateSubkey { + pk.IsSubkey = true + } + p = pk + case packetTypePublicKey, packetTypePublicSubkey: + var version byte + if contents, version, err = peekVersion(contents); err != nil { + return + } + isSubkey := tag == packetTypePublicSubkey + if version < 4 { + p = &PublicKeyV3{IsSubkey: isSubkey} + } else { + p = &PublicKey{IsSubkey: isSubkey} + } + case packetTypeCompressed: + p = new(Compressed) + case packetTypeSymmetricallyEncrypted: + p = new(SymmetricallyEncrypted) + case packetTypeLiteralData: + p = new(LiteralData) + case packetTypeUserId: + p = new(UserId) + case packetTypeUserAttribute: + p = new(UserAttribute) + case packetTypeSymmetricallyEncryptedMDC: + se := new(SymmetricallyEncrypted) + se.MDC = true + p = se + default: + err = errors.UnknownPacketTypeError(tag) + } + if p != nil { + err = p.parse(contents) + } + if err != nil { + consumeAll(contents) + } + return +} + +// SignatureType represents the different semantic meanings of an OpenPGP +// signature. See RFC 4880, section 5.2.1. +type SignatureType uint8 + +const ( + SigTypeBinary SignatureType = 0 + SigTypeText = 1 + SigTypeGenericCert = 0x10 + SigTypePersonaCert = 0x11 + SigTypeCasualCert = 0x12 + SigTypePositiveCert = 0x13 + SigTypeSubkeyBinding = 0x18 + SigTypePrimaryKeyBinding = 0x19 + SigTypeDirectSignature = 0x1F + SigTypeKeyRevocation = 0x20 + SigTypeSubkeyRevocation = 0x28 +) + +// PublicKeyAlgorithm represents the different public key system specified for +// OpenPGP. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12 +type PublicKeyAlgorithm uint8 + +const ( + PubKeyAlgoRSA PublicKeyAlgorithm = 1 + PubKeyAlgoElGamal PublicKeyAlgorithm = 16 + PubKeyAlgoDSA PublicKeyAlgorithm = 17 + // RFC 6637, Section 5. + PubKeyAlgoECDH PublicKeyAlgorithm = 18 + PubKeyAlgoECDSA PublicKeyAlgorithm = 19 + + // Deprecated in RFC 4880, Section 13.5. Use key flags instead. + PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2 + PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3 +) + +// CanEncrypt returns true if it's possible to encrypt a message to a public +// key of the given type. +func (pka PublicKeyAlgorithm) CanEncrypt() bool { + switch pka { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal: + return true + } + return false +} + +// CanSign returns true if it's possible for a public key of the given type to +// sign a message. +func (pka PublicKeyAlgorithm) CanSign() bool { + switch pka { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: + return true + } + return false +} + +// CipherFunction represents the different block ciphers specified for OpenPGP. See +// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13 +type CipherFunction uint8 + +const ( + Cipher3DES CipherFunction = 2 + CipherCAST5 CipherFunction = 3 + CipherAES128 CipherFunction = 7 + CipherAES192 CipherFunction = 8 + CipherAES256 CipherFunction = 9 +) + +// KeySize returns the key size, in bytes, of cipher. +func (cipher CipherFunction) KeySize() int { + switch cipher { + case Cipher3DES: + return 24 + case CipherCAST5: + return cast5.KeySize + case CipherAES128: + return 16 + case CipherAES192: + return 24 + case CipherAES256: + return 32 + } + return 0 +} + +// blockSize returns the block size, in bytes, of cipher. +func (cipher CipherFunction) blockSize() int { + switch cipher { + case Cipher3DES: + return des.BlockSize + case CipherCAST5: + return 8 + case CipherAES128, CipherAES192, CipherAES256: + return 16 + } + return 0 +} + +// new returns a fresh instance of the given cipher. +func (cipher CipherFunction) new(key []byte) (block cipher.Block) { + switch cipher { + case Cipher3DES: + block, _ = des.NewTripleDESCipher(key) + case CipherCAST5: + block, _ = cast5.NewCipher(key) + case CipherAES128, CipherAES192, CipherAES256: + block, _ = aes.NewCipher(key) + } + return +} + +// readMPI reads a big integer from r. The bit length returned is the bit +// length that was specified in r. This is preserved so that the integer can be +// reserialized exactly. +func readMPI(r io.Reader) (mpi []byte, bitLength uint16, err error) { + var buf [2]byte + _, err = readFull(r, buf[0:]) + if err != nil { + return + } + bitLength = uint16(buf[0])<<8 | uint16(buf[1]) + numBytes := (int(bitLength) + 7) / 8 + mpi = make([]byte, numBytes) + _, err = readFull(r, mpi) + // According to RFC 4880 3.2. we should check that the MPI has no leading + // zeroes (at least when not an encrypted MPI?), but this implementation + // does generate leading zeroes, so we keep accepting them. + return +} + +// writeMPI serializes a big integer to w. +func writeMPI(w io.Writer, bitLength uint16, mpiBytes []byte) (err error) { + // Note that we can produce leading zeroes, in violation of RFC 4880 3.2. + // Implementations seem to be tolerant of them, and stripping them would + // make it complex to guarantee matching re-serialization. + _, err = w.Write([]byte{byte(bitLength >> 8), byte(bitLength)}) + if err == nil { + _, err = w.Write(mpiBytes) + } + return +} + +// writeBig serializes a *big.Int to w. +func writeBig(w io.Writer, i *big.Int) error { + return writeMPI(w, uint16(i.BitLen()), i.Bytes()) +} + +// padToKeySize left-pads a MPI with zeroes to match the length of the +// specified RSA public. +func padToKeySize(pub *rsa.PublicKey, b []byte) []byte { + k := (pub.N.BitLen() + 7) / 8 + if len(b) >= k { + return b + } + bb := make([]byte, k) + copy(bb[len(bb)-len(b):], b) + return bb +} + +// CompressionAlgo Represents the different compression algorithms +// supported by OpenPGP (except for BZIP2, which is not currently +// supported). See Section 9.3 of RFC 4880. +type CompressionAlgo uint8 + +const ( + CompressionNone CompressionAlgo = 0 + CompressionZIP CompressionAlgo = 1 + CompressionZLIB CompressionAlgo = 2 +) diff --git a/vendor/golang.org/x/crypto/openpgp/packet/private_key.go b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go new file mode 100644 index 0000000000..192aac376d --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/private_key.go @@ -0,0 +1,384 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto" + "crypto/cipher" + "crypto/dsa" + "crypto/ecdsa" + "crypto/rsa" + "crypto/sha1" + "io" + "math/big" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/elgamal" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" +) + +// PrivateKey represents a possibly encrypted private key. See RFC 4880, +// section 5.5.3. +type PrivateKey struct { + PublicKey + Encrypted bool // if true then the private key is unavailable until Decrypt has been called. + encryptedData []byte + cipher CipherFunction + s2k func(out, in []byte) + PrivateKey interface{} // An *{rsa|dsa|ecdsa}.PrivateKey or crypto.Signer/crypto.Decrypter (Decryptor RSA only). + sha1Checksum bool + iv []byte +} + +func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey { + pk := new(PrivateKey) + pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey) + pk.PrivateKey = priv + return pk +} + +// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that +// implements RSA or ECDSA. +func NewSignerPrivateKey(creationTime time.Time, signer crypto.Signer) *PrivateKey { + pk := new(PrivateKey) + // In general, the public Keys should be used as pointers. We still + // type-switch on the values, for backwards-compatibility. + switch pubkey := signer.Public().(type) { + case *rsa.PublicKey: + pk.PublicKey = *NewRSAPublicKey(creationTime, pubkey) + case rsa.PublicKey: + pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey) + case *ecdsa.PublicKey: + pk.PublicKey = *NewECDSAPublicKey(creationTime, pubkey) + case ecdsa.PublicKey: + pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey) + default: + panic("openpgp: unknown crypto.Signer type in NewSignerPrivateKey") + } + pk.PrivateKey = signer + return pk +} + +func (pk *PrivateKey) parse(r io.Reader) (err error) { + err = (&pk.PublicKey).parse(r) + if err != nil { + return + } + var buf [1]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + + s2kType := buf[0] + + switch s2kType { + case 0: + pk.s2k = nil + pk.Encrypted = false + case 254, 255: + _, err = readFull(r, buf[:]) + if err != nil { + return + } + pk.cipher = CipherFunction(buf[0]) + pk.Encrypted = true + pk.s2k, err = s2k.Parse(r) + if err != nil { + return + } + if s2kType == 254 { + pk.sha1Checksum = true + } + default: + return errors.UnsupportedError("deprecated s2k function in private key") + } + + if pk.Encrypted { + blockSize := pk.cipher.blockSize() + if blockSize == 0 { + return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher))) + } + pk.iv = make([]byte, blockSize) + _, err = readFull(r, pk.iv) + if err != nil { + return + } + } + + pk.encryptedData, err = io.ReadAll(r) + if err != nil { + return + } + + if !pk.Encrypted { + return pk.parsePrivateKey(pk.encryptedData) + } + + return +} + +func mod64kHash(d []byte) uint16 { + var h uint16 + for _, b := range d { + h += uint16(b) + } + return h +} + +func (pk *PrivateKey) Serialize(w io.Writer) (err error) { + // TODO(agl): support encrypted private keys + buf := bytes.NewBuffer(nil) + err = pk.PublicKey.serializeWithoutHeaders(buf) + if err != nil { + return + } + buf.WriteByte(0 /* no encryption */) + + privateKeyBuf := bytes.NewBuffer(nil) + + switch priv := pk.PrivateKey.(type) { + case *rsa.PrivateKey: + err = serializeRSAPrivateKey(privateKeyBuf, priv) + case *dsa.PrivateKey: + err = serializeDSAPrivateKey(privateKeyBuf, priv) + case *elgamal.PrivateKey: + err = serializeElGamalPrivateKey(privateKeyBuf, priv) + case *ecdsa.PrivateKey: + err = serializeECDSAPrivateKey(privateKeyBuf, priv) + default: + err = errors.InvalidArgumentError("unknown private key type") + } + if err != nil { + return + } + + ptype := packetTypePrivateKey + contents := buf.Bytes() + privateKeyBytes := privateKeyBuf.Bytes() + if pk.IsSubkey { + ptype = packetTypePrivateSubkey + } + err = serializeHeader(w, ptype, len(contents)+len(privateKeyBytes)+2) + if err != nil { + return + } + _, err = w.Write(contents) + if err != nil { + return + } + _, err = w.Write(privateKeyBytes) + if err != nil { + return + } + + checksum := mod64kHash(privateKeyBytes) + var checksumBytes [2]byte + checksumBytes[0] = byte(checksum >> 8) + checksumBytes[1] = byte(checksum) + _, err = w.Write(checksumBytes[:]) + + return +} + +func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error { + err := writeBig(w, priv.D) + if err != nil { + return err + } + err = writeBig(w, priv.Primes[1]) + if err != nil { + return err + } + err = writeBig(w, priv.Primes[0]) + if err != nil { + return err + } + return writeBig(w, priv.Precomputed.Qinv) +} + +func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error { + return writeBig(w, priv.X) +} + +func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error { + return writeBig(w, priv.X) +} + +func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error { + return writeBig(w, priv.D) +} + +// Decrypt decrypts an encrypted private key using a passphrase. +func (pk *PrivateKey) Decrypt(passphrase []byte) error { + if !pk.Encrypted { + return nil + } + + key := make([]byte, pk.cipher.KeySize()) + pk.s2k(key, passphrase) + block := pk.cipher.new(key) + cfb := cipher.NewCFBDecrypter(block, pk.iv) + + data := make([]byte, len(pk.encryptedData)) + cfb.XORKeyStream(data, pk.encryptedData) + + if pk.sha1Checksum { + if len(data) < sha1.Size { + return errors.StructuralError("truncated private key data") + } + h := sha1.New() + h.Write(data[:len(data)-sha1.Size]) + sum := h.Sum(nil) + if !bytes.Equal(sum, data[len(data)-sha1.Size:]) { + return errors.StructuralError("private key checksum failure") + } + data = data[:len(data)-sha1.Size] + } else { + if len(data) < 2 { + return errors.StructuralError("truncated private key data") + } + var sum uint16 + for i := 0; i < len(data)-2; i++ { + sum += uint16(data[i]) + } + if data[len(data)-2] != uint8(sum>>8) || + data[len(data)-1] != uint8(sum) { + return errors.StructuralError("private key checksum failure") + } + data = data[:len(data)-2] + } + + return pk.parsePrivateKey(data) +} + +func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) { + switch pk.PublicKey.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly: + return pk.parseRSAPrivateKey(data) + case PubKeyAlgoDSA: + return pk.parseDSAPrivateKey(data) + case PubKeyAlgoElGamal: + return pk.parseElGamalPrivateKey(data) + case PubKeyAlgoECDSA: + return pk.parseECDSAPrivateKey(data) + } + panic("impossible") +} + +func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) { + rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey) + rsaPriv := new(rsa.PrivateKey) + rsaPriv.PublicKey = *rsaPub + + buf := bytes.NewBuffer(data) + d, _, err := readMPI(buf) + if err != nil { + return + } + p, _, err := readMPI(buf) + if err != nil { + return + } + q, _, err := readMPI(buf) + if err != nil { + return + } + + rsaPriv.D = new(big.Int).SetBytes(d) + rsaPriv.Primes = make([]*big.Int, 2) + rsaPriv.Primes[0] = new(big.Int).SetBytes(p) + rsaPriv.Primes[1] = new(big.Int).SetBytes(q) + if err := rsaPriv.Validate(); err != nil { + return err + } + rsaPriv.Precompute() + pk.PrivateKey = rsaPriv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) { + dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey) + dsaPriv := new(dsa.PrivateKey) + dsaPriv.PublicKey = *dsaPub + + buf := bytes.NewBuffer(data) + x, _, err := readMPI(buf) + if err != nil { + return + } + + dsaPriv.X = new(big.Int).SetBytes(x) + pk.PrivateKey = dsaPriv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) { + pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey) + priv := new(elgamal.PrivateKey) + priv.PublicKey = *pub + + buf := bytes.NewBuffer(data) + x, _, err := readMPI(buf) + if err != nil { + return + } + + priv.X = new(big.Int).SetBytes(x) + pk.PrivateKey = priv + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} + +func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) { + ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey) + + buf := bytes.NewBuffer(data) + d, _, err := readMPI(buf) + if err != nil { + return + } + + pk.PrivateKey = &ecdsa.PrivateKey{ + PublicKey: *ecdsaPub, + D: new(big.Int).SetBytes(d), + } + pk.Encrypted = false + pk.encryptedData = nil + + return nil +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go new file mode 100644 index 0000000000..fcd5f52519 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key.go @@ -0,0 +1,753 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rsa" + "crypto/sha1" + _ "crypto/sha256" + _ "crypto/sha512" + "encoding/binary" + "fmt" + "hash" + "io" + "math/big" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/elgamal" + "golang.org/x/crypto/openpgp/errors" +) + +var ( + // NIST curve P-256 + oidCurveP256 []byte = []byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07} + // NIST curve P-384 + oidCurveP384 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x22} + // NIST curve P-521 + oidCurveP521 []byte = []byte{0x2B, 0x81, 0x04, 0x00, 0x23} +) + +const maxOIDLength = 8 + +// ecdsaKey stores the algorithm-specific fields for ECDSA keys. +// as defined in RFC 6637, Section 9. +type ecdsaKey struct { + // oid contains the OID byte sequence identifying the elliptic curve used + oid []byte + // p contains the elliptic curve point that represents the public key + p parsedMPI +} + +// parseOID reads the OID for the curve as defined in RFC 6637, Section 9. +func parseOID(r io.Reader) (oid []byte, err error) { + buf := make([]byte, maxOIDLength) + if _, err = readFull(r, buf[:1]); err != nil { + return + } + oidLen := buf[0] + if int(oidLen) > len(buf) { + err = errors.UnsupportedError("invalid oid length: " + strconv.Itoa(int(oidLen))) + return + } + oid = buf[:oidLen] + _, err = readFull(r, oid) + return +} + +func (f *ecdsaKey) parse(r io.Reader) (err error) { + if f.oid, err = parseOID(r); err != nil { + return err + } + f.p.bytes, f.p.bitLength, err = readMPI(r) + return +} + +func (f *ecdsaKey) serialize(w io.Writer) (err error) { + buf := make([]byte, maxOIDLength+1) + buf[0] = byte(len(f.oid)) + copy(buf[1:], f.oid) + if _, err = w.Write(buf[:len(f.oid)+1]); err != nil { + return + } + return writeMPIs(w, f.p) +} + +func (f *ecdsaKey) newECDSA() (*ecdsa.PublicKey, error) { + var c elliptic.Curve + if bytes.Equal(f.oid, oidCurveP256) { + c = elliptic.P256() + } else if bytes.Equal(f.oid, oidCurveP384) { + c = elliptic.P384() + } else if bytes.Equal(f.oid, oidCurveP521) { + c = elliptic.P521() + } else { + return nil, errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", f.oid)) + } + x, y := elliptic.Unmarshal(c, f.p.bytes) + if x == nil { + return nil, errors.UnsupportedError("failed to parse EC point") + } + return &ecdsa.PublicKey{Curve: c, X: x, Y: y}, nil +} + +func (f *ecdsaKey) byteLen() int { + return 1 + len(f.oid) + 2 + len(f.p.bytes) +} + +type kdfHashFunction byte +type kdfAlgorithm byte + +// ecdhKdf stores key derivation function parameters +// used for ECDH encryption. See RFC 6637, Section 9. +type ecdhKdf struct { + KdfHash kdfHashFunction + KdfAlgo kdfAlgorithm +} + +func (f *ecdhKdf) parse(r io.Reader) (err error) { + buf := make([]byte, 1) + if _, err = readFull(r, buf); err != nil { + return + } + kdfLen := int(buf[0]) + if kdfLen < 3 { + return errors.UnsupportedError("Unsupported ECDH KDF length: " + strconv.Itoa(kdfLen)) + } + buf = make([]byte, kdfLen) + if _, err = readFull(r, buf); err != nil { + return + } + reserved := int(buf[0]) + f.KdfHash = kdfHashFunction(buf[1]) + f.KdfAlgo = kdfAlgorithm(buf[2]) + if reserved != 0x01 { + return errors.UnsupportedError("Unsupported KDF reserved field: " + strconv.Itoa(reserved)) + } + return +} + +func (f *ecdhKdf) serialize(w io.Writer) (err error) { + buf := make([]byte, 4) + // See RFC 6637, Section 9, Algorithm-Specific Fields for ECDH keys. + buf[0] = byte(0x03) // Length of the following fields + buf[1] = byte(0x01) // Reserved for future extensions, must be 1 for now + buf[2] = byte(f.KdfHash) + buf[3] = byte(f.KdfAlgo) + _, err = w.Write(buf[:]) + return +} + +func (f *ecdhKdf) byteLen() int { + return 4 +} + +// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2. +type PublicKey struct { + CreationTime time.Time + PubKeyAlgo PublicKeyAlgorithm + PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey or *ecdsa.PublicKey + Fingerprint [20]byte + KeyId uint64 + IsSubkey bool + + n, e, p, q, g, y parsedMPI + + // RFC 6637 fields + ec *ecdsaKey + ecdh *ecdhKdf +} + +// signingKey provides a convenient abstraction over signature verification +// for v3 and v4 public keys. +type signingKey interface { + SerializeSignaturePrefix(io.Writer) + serializeWithoutHeaders(io.Writer) error +} + +func fromBig(n *big.Int) parsedMPI { + return parsedMPI{ + bytes: n.Bytes(), + bitLength: uint16(n.BitLen()), + } +} + +// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey. +func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoRSA, + PublicKey: pub, + n: fromBig(pub.N), + e: fromBig(big.NewInt(int64(pub.E))), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey. +func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoDSA, + PublicKey: pub, + p: fromBig(pub.P), + q: fromBig(pub.Q), + g: fromBig(pub.G), + y: fromBig(pub.Y), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey. +func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoElGamal, + PublicKey: pub, + p: fromBig(pub.P), + g: fromBig(pub.G), + y: fromBig(pub.Y), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey { + pk := &PublicKey{ + CreationTime: creationTime, + PubKeyAlgo: PubKeyAlgoECDSA, + PublicKey: pub, + ec: new(ecdsaKey), + } + + switch pub.Curve { + case elliptic.P256(): + pk.ec.oid = oidCurveP256 + case elliptic.P384(): + pk.ec.oid = oidCurveP384 + case elliptic.P521(): + pk.ec.oid = oidCurveP521 + default: + panic("unknown elliptic curve") + } + + pk.ec.p.bytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y) + + // The bit length is 3 (for the 0x04 specifying an uncompressed key) + // plus two field elements (for x and y), which are rounded up to the + // nearest byte. See https://tools.ietf.org/html/rfc6637#section-6 + fieldBytes := (pub.Curve.Params().BitSize + 7) & ^7 + pk.ec.p.bitLength = uint16(3 + fieldBytes + fieldBytes) + + pk.setFingerPrintAndKeyId() + return pk +} + +func (pk *PublicKey) parse(r io.Reader) (err error) { + // RFC 4880, section 5.5.2 + var buf [6]byte + _, err = readFull(r, buf[:]) + if err != nil { + return + } + if buf[0] != 4 { + return errors.UnsupportedError("public key version") + } + pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) + pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5]) + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + err = pk.parseRSA(r) + case PubKeyAlgoDSA: + err = pk.parseDSA(r) + case PubKeyAlgoElGamal: + err = pk.parseElGamal(r) + case PubKeyAlgoECDSA: + pk.ec = new(ecdsaKey) + if err = pk.ec.parse(r); err != nil { + return err + } + pk.PublicKey, err = pk.ec.newECDSA() + case PubKeyAlgoECDH: + pk.ec = new(ecdsaKey) + if err = pk.ec.parse(r); err != nil { + return + } + pk.ecdh = new(ecdhKdf) + if err = pk.ecdh.parse(r); err != nil { + return + } + // The ECDH key is stored in an ecdsa.PublicKey for convenience. + pk.PublicKey, err = pk.ec.newECDSA() + default: + err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) + } + if err != nil { + return + } + + pk.setFingerPrintAndKeyId() + return +} + +func (pk *PublicKey) setFingerPrintAndKeyId() { + // RFC 4880, section 12.2 + fingerPrint := sha1.New() + pk.SerializeSignaturePrefix(fingerPrint) + pk.serializeWithoutHeaders(fingerPrint) + copy(pk.Fingerprint[:], fingerPrint.Sum(nil)) + pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20]) +} + +// parseRSA parses RSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKey) parseRSA(r io.Reader) (err error) { + pk.n.bytes, pk.n.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.e.bytes, pk.e.bitLength, err = readMPI(r) + if err != nil { + return + } + + if len(pk.e.bytes) > 3 { + err = errors.UnsupportedError("large public exponent") + return + } + rsa := &rsa.PublicKey{ + N: new(big.Int).SetBytes(pk.n.bytes), + E: 0, + } + for i := 0; i < len(pk.e.bytes); i++ { + rsa.E <<= 8 + rsa.E |= int(pk.e.bytes[i]) + } + pk.PublicKey = rsa + return +} + +// parseDSA parses DSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKey) parseDSA(r io.Reader) (err error) { + pk.p.bytes, pk.p.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.q.bytes, pk.q.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.g.bytes, pk.g.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.y.bytes, pk.y.bitLength, err = readMPI(r) + if err != nil { + return + } + + dsa := new(dsa.PublicKey) + dsa.P = new(big.Int).SetBytes(pk.p.bytes) + dsa.Q = new(big.Int).SetBytes(pk.q.bytes) + dsa.G = new(big.Int).SetBytes(pk.g.bytes) + dsa.Y = new(big.Int).SetBytes(pk.y.bytes) + pk.PublicKey = dsa + return +} + +// parseElGamal parses ElGamal public key material from the given Reader. See +// RFC 4880, section 5.5.2. +func (pk *PublicKey) parseElGamal(r io.Reader) (err error) { + pk.p.bytes, pk.p.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.g.bytes, pk.g.bitLength, err = readMPI(r) + if err != nil { + return + } + pk.y.bytes, pk.y.bitLength, err = readMPI(r) + if err != nil { + return + } + + elgamal := new(elgamal.PublicKey) + elgamal.P = new(big.Int).SetBytes(pk.p.bytes) + elgamal.G = new(big.Int).SetBytes(pk.g.bytes) + elgamal.Y = new(big.Int).SetBytes(pk.y.bytes) + pk.PublicKey = elgamal + return +} + +// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. +// The prefix is used when calculating a signature over this public key. See +// RFC 4880, section 5.2.4. +func (pk *PublicKey) SerializeSignaturePrefix(h io.Writer) { + var pLength uint16 + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + pLength += 2 + uint16(len(pk.n.bytes)) + pLength += 2 + uint16(len(pk.e.bytes)) + case PubKeyAlgoDSA: + pLength += 2 + uint16(len(pk.p.bytes)) + pLength += 2 + uint16(len(pk.q.bytes)) + pLength += 2 + uint16(len(pk.g.bytes)) + pLength += 2 + uint16(len(pk.y.bytes)) + case PubKeyAlgoElGamal: + pLength += 2 + uint16(len(pk.p.bytes)) + pLength += 2 + uint16(len(pk.g.bytes)) + pLength += 2 + uint16(len(pk.y.bytes)) + case PubKeyAlgoECDSA: + pLength += uint16(pk.ec.byteLen()) + case PubKeyAlgoECDH: + pLength += uint16(pk.ec.byteLen()) + pLength += uint16(pk.ecdh.byteLen()) + default: + panic("unknown public key algorithm") + } + pLength += 6 + h.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) + return +} + +func (pk *PublicKey) Serialize(w io.Writer) (err error) { + length := 6 // 6 byte header + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + length += 2 + len(pk.n.bytes) + length += 2 + len(pk.e.bytes) + case PubKeyAlgoDSA: + length += 2 + len(pk.p.bytes) + length += 2 + len(pk.q.bytes) + length += 2 + len(pk.g.bytes) + length += 2 + len(pk.y.bytes) + case PubKeyAlgoElGamal: + length += 2 + len(pk.p.bytes) + length += 2 + len(pk.g.bytes) + length += 2 + len(pk.y.bytes) + case PubKeyAlgoECDSA: + length += pk.ec.byteLen() + case PubKeyAlgoECDH: + length += pk.ec.byteLen() + length += pk.ecdh.byteLen() + default: + panic("unknown public key algorithm") + } + + packetType := packetTypePublicKey + if pk.IsSubkey { + packetType = packetTypePublicSubkey + } + err = serializeHeader(w, packetType, length) + if err != nil { + return + } + return pk.serializeWithoutHeaders(w) +} + +// serializeWithoutHeaders marshals the PublicKey to w in the form of an +// OpenPGP public key packet, not including the packet header. +func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) { + var buf [6]byte + buf[0] = 4 + t := uint32(pk.CreationTime.Unix()) + buf[1] = byte(t >> 24) + buf[2] = byte(t >> 16) + buf[3] = byte(t >> 8) + buf[4] = byte(t) + buf[5] = byte(pk.PubKeyAlgo) + + _, err = w.Write(buf[:]) + if err != nil { + return + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + return writeMPIs(w, pk.n, pk.e) + case PubKeyAlgoDSA: + return writeMPIs(w, pk.p, pk.q, pk.g, pk.y) + case PubKeyAlgoElGamal: + return writeMPIs(w, pk.p, pk.g, pk.y) + case PubKeyAlgoECDSA: + return pk.ec.serialize(w) + case PubKeyAlgoECDH: + if err = pk.ec.serialize(w); err != nil { + return + } + return pk.ecdh.serialize(w) + } + return errors.InvalidArgumentError("bad public-key algorithm") +} + +// CanSign returns true iff this public key can generate signatures +func (pk *PublicKey) CanSign() bool { + return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal +} + +// VerifySignature returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + signed.Write(sig.HashSuffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey) + err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)) + if err != nil { + return errors.SignatureError("RSA verification failure") + } + return nil + case PubKeyAlgoDSA: + dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey) + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 + if len(hashBytes) > subgroupSize { + hashBytes = hashBytes[:subgroupSize] + } + if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { + return errors.SignatureError("DSA verification failure") + } + return nil + case PubKeyAlgoECDSA: + ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey) + if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.bytes), new(big.Int).SetBytes(sig.ECDSASigS.bytes)) { + return errors.SignatureError("ECDSA verification failure") + } + return nil + default: + return errors.SignatureError("Unsupported public key algorithm used in signature") + } +} + +// VerifySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKey) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + suffix := make([]byte, 5) + suffix[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) + signed.Write(suffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + rsaPublicKey := pk.PublicKey.(*rsa.PublicKey) + if err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.bytes)); err != nil { + return errors.SignatureError("RSA verification failure") + } + return + case PubKeyAlgoDSA: + dsaPublicKey := pk.PublicKey.(*dsa.PublicKey) + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8 + if len(hashBytes) > subgroupSize { + hashBytes = hashBytes[:subgroupSize] + } + if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.bytes), new(big.Int).SetBytes(sig.DSASigS.bytes)) { + return errors.SignatureError("DSA verification failure") + } + return nil + default: + panic("shouldn't happen") + } +} + +// keySignatureHash returns a Hash of the message that needs to be signed for +// pk to assert a subkey relationship to signed. +func keySignatureHash(pk, signed signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + signed.SerializeSignaturePrefix(h) + signed.serializeWithoutHeaders(h) + return +} + +// VerifyKeySignature returns nil iff sig is a valid signature, made by this +// public key, of signed. +func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error { + h, err := keySignatureHash(pk, signed, sig.Hash) + if err != nil { + return err + } + if err = pk.VerifySignature(h, sig); err != nil { + return err + } + + if sig.FlagSign { + // Signing subkeys must be cross-signed. See + // https://www.gnupg.org/faq/subkey-cross-certify.html. + if sig.EmbeddedSignature == nil { + return errors.StructuralError("signing subkey is missing cross-signature") + } + // Verify the cross-signature. This is calculated over the same + // data as the main signature, so we cannot just recursively + // call signed.VerifyKeySignature(...) + if h, err = keySignatureHash(pk, signed, sig.EmbeddedSignature.Hash); err != nil { + return errors.StructuralError("error while hashing for cross-signature: " + err.Error()) + } + if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil { + return errors.StructuralError("error while verifying cross-signature: " + err.Error()) + } + } + + return nil +} + +func keyRevocationHash(pk signingKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + return +} + +// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this +// public key. +func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) { + h, err := keyRevocationHash(pk, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +// userIdSignatureHash returns a Hash of the message that needs to be signed +// to assert that pk is a valid key for id. +func userIdSignatureHash(id string, pk *PublicKey, hashFunc crypto.Hash) (h hash.Hash, err error) { + if !hashFunc.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hashFunc.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + var buf [5]byte + buf[0] = 0xb4 + buf[1] = byte(len(id) >> 24) + buf[2] = byte(len(id) >> 16) + buf[3] = byte(len(id) >> 8) + buf[4] = byte(len(id)) + h.Write(buf[:]) + h.Write([]byte(id)) + + return +} + +// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) { + h, err := userIdSignatureHash(id, pub, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignature(h, sig) +} + +// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKey) VerifyUserIdSignatureV3(id string, pub *PublicKey, sig *SignatureV3) (err error) { + h, err := userIdSignatureV3Hash(id, pub, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// KeyIdString returns the public key's fingerprint in capital hex +// (e.g. "6C7EE1B8621CC013"). +func (pk *PublicKey) KeyIdString() string { + return fmt.Sprintf("%X", pk.Fingerprint[12:20]) +} + +// KeyIdShortString returns the short form of public key's fingerprint +// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). +func (pk *PublicKey) KeyIdShortString() string { + return fmt.Sprintf("%X", pk.Fingerprint[16:20]) +} + +// A parsedMPI is used to store the contents of a big integer, along with the +// bit length that was specified in the original input. This allows the MPI to +// be reserialized exactly. +type parsedMPI struct { + bytes []byte + bitLength uint16 +} + +// writeMPIs is a utility function for serializing several big integers to the +// given Writer. +func writeMPIs(w io.Writer, mpis ...parsedMPI) (err error) { + for _, mpi := range mpis { + err = writeMPI(w, mpi.bitLength, mpi.bytes) + if err != nil { + return + } + } + return +} + +// BitLength returns the bit length for the given public key. +func (pk *PublicKey) BitLength() (bitLength uint16, err error) { + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + bitLength = pk.n.bitLength + case PubKeyAlgoDSA: + bitLength = pk.p.bitLength + case PubKeyAlgoElGamal: + bitLength = pk.p.bitLength + default: + err = errors.InvalidArgumentError("bad public-key algorithm") + } + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go new file mode 100644 index 0000000000..5daf7b6cfd --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/public_key_v3.go @@ -0,0 +1,279 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "crypto/md5" + "crypto/rsa" + "encoding/binary" + "fmt" + "hash" + "io" + "math/big" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/errors" +) + +// PublicKeyV3 represents older, version 3 public keys. These keys are less secure and +// should not be used for signing or encrypting. They are supported here only for +// parsing version 3 key material and validating signatures. +// See RFC 4880, section 5.5.2. +type PublicKeyV3 struct { + CreationTime time.Time + DaysToExpire uint16 + PubKeyAlgo PublicKeyAlgorithm + PublicKey *rsa.PublicKey + Fingerprint [16]byte + KeyId uint64 + IsSubkey bool + + n, e parsedMPI +} + +// newRSAPublicKeyV3 returns a PublicKey that wraps the given rsa.PublicKey. +// Included here for testing purposes only. RFC 4880, section 5.5.2: +// "an implementation MUST NOT generate a V3 key, but MAY accept it." +func newRSAPublicKeyV3(creationTime time.Time, pub *rsa.PublicKey) *PublicKeyV3 { + pk := &PublicKeyV3{ + CreationTime: creationTime, + PublicKey: pub, + n: fromBig(pub.N), + e: fromBig(big.NewInt(int64(pub.E))), + } + + pk.setFingerPrintAndKeyId() + return pk +} + +func (pk *PublicKeyV3) parse(r io.Reader) (err error) { + // RFC 4880, section 5.5.2 + var buf [8]byte + if _, err = readFull(r, buf[:]); err != nil { + return + } + if buf[0] < 2 || buf[0] > 3 { + return errors.UnsupportedError("public key version") + } + pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0) + pk.DaysToExpire = binary.BigEndian.Uint16(buf[5:7]) + pk.PubKeyAlgo = PublicKeyAlgorithm(buf[7]) + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + err = pk.parseRSA(r) + default: + err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo))) + } + if err != nil { + return + } + + pk.setFingerPrintAndKeyId() + return +} + +func (pk *PublicKeyV3) setFingerPrintAndKeyId() { + // RFC 4880, section 12.2 + fingerPrint := md5.New() + fingerPrint.Write(pk.n.bytes) + fingerPrint.Write(pk.e.bytes) + fingerPrint.Sum(pk.Fingerprint[:0]) + pk.KeyId = binary.BigEndian.Uint64(pk.n.bytes[len(pk.n.bytes)-8:]) +} + +// parseRSA parses RSA public key material from the given Reader. See RFC 4880, +// section 5.5.2. +func (pk *PublicKeyV3) parseRSA(r io.Reader) (err error) { + if pk.n.bytes, pk.n.bitLength, err = readMPI(r); err != nil { + return + } + if pk.e.bytes, pk.e.bitLength, err = readMPI(r); err != nil { + return + } + + // RFC 4880 Section 12.2 requires the low 8 bytes of the + // modulus to form the key id. + if len(pk.n.bytes) < 8 { + return errors.StructuralError("v3 public key modulus is too short") + } + if len(pk.e.bytes) > 3 { + err = errors.UnsupportedError("large public exponent") + return + } + rsa := &rsa.PublicKey{N: new(big.Int).SetBytes(pk.n.bytes)} + for i := 0; i < len(pk.e.bytes); i++ { + rsa.E <<= 8 + rsa.E |= int(pk.e.bytes[i]) + } + pk.PublicKey = rsa + return +} + +// SerializeSignaturePrefix writes the prefix for this public key to the given Writer. +// The prefix is used when calculating a signature over this public key. See +// RFC 4880, section 5.2.4. +func (pk *PublicKeyV3) SerializeSignaturePrefix(w io.Writer) { + var pLength uint16 + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + pLength += 2 + uint16(len(pk.n.bytes)) + pLength += 2 + uint16(len(pk.e.bytes)) + default: + panic("unknown public key algorithm") + } + pLength += 6 + w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}) + return +} + +func (pk *PublicKeyV3) Serialize(w io.Writer) (err error) { + length := 8 // 8 byte header + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + length += 2 + len(pk.n.bytes) + length += 2 + len(pk.e.bytes) + default: + panic("unknown public key algorithm") + } + + packetType := packetTypePublicKey + if pk.IsSubkey { + packetType = packetTypePublicSubkey + } + if err = serializeHeader(w, packetType, length); err != nil { + return + } + return pk.serializeWithoutHeaders(w) +} + +// serializeWithoutHeaders marshals the PublicKey to w in the form of an +// OpenPGP public key packet, not including the packet header. +func (pk *PublicKeyV3) serializeWithoutHeaders(w io.Writer) (err error) { + var buf [8]byte + // Version 3 + buf[0] = 3 + // Creation time + t := uint32(pk.CreationTime.Unix()) + buf[1] = byte(t >> 24) + buf[2] = byte(t >> 16) + buf[3] = byte(t >> 8) + buf[4] = byte(t) + // Days to expire + buf[5] = byte(pk.DaysToExpire >> 8) + buf[6] = byte(pk.DaysToExpire) + // Public key algorithm + buf[7] = byte(pk.PubKeyAlgo) + + if _, err = w.Write(buf[:]); err != nil { + return + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + return writeMPIs(w, pk.n, pk.e) + } + return errors.InvalidArgumentError("bad public-key algorithm") +} + +// CanSign returns true iff this public key can generate signatures +func (pk *PublicKeyV3) CanSign() bool { + return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly +} + +// VerifySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of the data hashed into signed. signed is mutated by this call. +func (pk *PublicKeyV3) VerifySignatureV3(signed hash.Hash, sig *SignatureV3) (err error) { + if !pk.CanSign() { + return errors.InvalidArgumentError("public key cannot generate signatures") + } + + suffix := make([]byte, 5) + suffix[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(suffix[1:], uint32(sig.CreationTime.Unix())) + signed.Write(suffix) + hashBytes := signed.Sum(nil) + + if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] { + return errors.SignatureError("hash tag doesn't match") + } + + if pk.PubKeyAlgo != sig.PubKeyAlgo { + return errors.InvalidArgumentError("public key and signature use different algorithms") + } + + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + if err = rsa.VerifyPKCS1v15(pk.PublicKey, sig.Hash, hashBytes, sig.RSASignature.bytes); err != nil { + return errors.SignatureError("RSA verification failure") + } + return + default: + // V3 public keys only support RSA. + panic("shouldn't happen") + } +} + +// VerifyUserIdSignatureV3 returns nil iff sig is a valid signature, made by this +// public key, that id is the identity of pub. +func (pk *PublicKeyV3) VerifyUserIdSignatureV3(id string, pub *PublicKeyV3, sig *SignatureV3) (err error) { + h, err := userIdSignatureV3Hash(id, pk, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// VerifyKeySignatureV3 returns nil iff sig is a valid signature, made by this +// public key, of signed. +func (pk *PublicKeyV3) VerifyKeySignatureV3(signed *PublicKeyV3, sig *SignatureV3) (err error) { + h, err := keySignatureHash(pk, signed, sig.Hash) + if err != nil { + return err + } + return pk.VerifySignatureV3(h, sig) +} + +// userIdSignatureV3Hash returns a Hash of the message that needs to be signed +// to assert that pk is a valid key for id. +func userIdSignatureV3Hash(id string, pk signingKey, hfn crypto.Hash) (h hash.Hash, err error) { + if !hfn.Available() { + return nil, errors.UnsupportedError("hash function") + } + h = hfn.New() + + // RFC 4880, section 5.2.4 + pk.SerializeSignaturePrefix(h) + pk.serializeWithoutHeaders(h) + + h.Write([]byte(id)) + + return +} + +// KeyIdString returns the public key's fingerprint in capital hex +// (e.g. "6C7EE1B8621CC013"). +func (pk *PublicKeyV3) KeyIdString() string { + return fmt.Sprintf("%X", pk.KeyId) +} + +// KeyIdShortString returns the short form of public key's fingerprint +// in capital hex, as shown by gpg --list-keys (e.g. "621CC013"). +func (pk *PublicKeyV3) KeyIdShortString() string { + return fmt.Sprintf("%X", pk.KeyId&0xFFFFFFFF) +} + +// BitLength returns the bit length for the given public key. +func (pk *PublicKeyV3) BitLength() (bitLength uint16, err error) { + switch pk.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly: + bitLength = pk.n.bitLength + default: + err = errors.InvalidArgumentError("bad public-key algorithm") + } + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/reader.go b/vendor/golang.org/x/crypto/openpgp/packet/reader.go new file mode 100644 index 0000000000..34bc7c613e --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/reader.go @@ -0,0 +1,76 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "golang.org/x/crypto/openpgp/errors" + "io" +) + +// Reader reads packets from an io.Reader and allows packets to be 'unread' so +// that they result from the next call to Next. +type Reader struct { + q []Packet + readers []io.Reader +} + +// New io.Readers are pushed when a compressed or encrypted packet is processed +// and recursively treated as a new source of packets. However, a carefully +// crafted packet can trigger an infinite recursive sequence of packets. See +// http://mumble.net/~campbell/misc/pgp-quine +// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402 +// This constant limits the number of recursive packets that may be pushed. +const maxReaders = 32 + +// Next returns the most recently unread Packet, or reads another packet from +// the top-most io.Reader. Unknown packet types are skipped. +func (r *Reader) Next() (p Packet, err error) { + if len(r.q) > 0 { + p = r.q[len(r.q)-1] + r.q = r.q[:len(r.q)-1] + return + } + + for len(r.readers) > 0 { + p, err = Read(r.readers[len(r.readers)-1]) + if err == nil { + return + } + if err == io.EOF { + r.readers = r.readers[:len(r.readers)-1] + continue + } + if _, ok := err.(errors.UnknownPacketTypeError); !ok { + return nil, err + } + } + + return nil, io.EOF +} + +// Push causes the Reader to start reading from a new io.Reader. When an EOF +// error is seen from the new io.Reader, it is popped and the Reader continues +// to read from the next most recent io.Reader. Push returns a StructuralError +// if pushing the reader would exceed the maximum recursion level, otherwise it +// returns nil. +func (r *Reader) Push(reader io.Reader) (err error) { + if len(r.readers) >= maxReaders { + return errors.StructuralError("too many layers of packets") + } + r.readers = append(r.readers, reader) + return nil +} + +// Unread causes the given Packet to be returned from the next call to Next. +func (r *Reader) Unread(p Packet) { + r.q = append(r.q, p) +} + +func NewReader(r io.Reader) *Reader { + return &Reader{ + q: nil, + readers: []io.Reader{r}, + } +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature.go b/vendor/golang.org/x/crypto/openpgp/packet/signature.go new file mode 100644 index 0000000000..b2a24a5323 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/signature.go @@ -0,0 +1,731 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto" + "crypto/dsa" + "crypto/ecdsa" + "encoding/asn1" + "encoding/binary" + "hash" + "io" + "math/big" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" +) + +const ( + // See RFC 4880, section 5.2.3.21 for details. + KeyFlagCertify = 1 << iota + KeyFlagSign + KeyFlagEncryptCommunications + KeyFlagEncryptStorage +) + +// Signature represents a signature. See RFC 4880, section 5.2. +type Signature struct { + SigType SignatureType + PubKeyAlgo PublicKeyAlgorithm + Hash crypto.Hash + + // HashSuffix is extra data that is hashed in after the signed data. + HashSuffix []byte + // HashTag contains the first two bytes of the hash for fast rejection + // of bad signed data. + HashTag [2]byte + CreationTime time.Time + + RSASignature parsedMPI + DSASigR, DSASigS parsedMPI + ECDSASigR, ECDSASigS parsedMPI + + // rawSubpackets contains the unparsed subpackets, in order. + rawSubpackets []outputSubpacket + + // The following are optional so are nil when not included in the + // signature. + + SigLifetimeSecs, KeyLifetimeSecs *uint32 + PreferredSymmetric, PreferredHash, PreferredCompression []uint8 + IssuerKeyId *uint64 + IsPrimaryId *bool + + // FlagsValid is set if any flags were given. See RFC 4880, section + // 5.2.3.21 for details. + FlagsValid bool + FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage bool + + // RevocationReason is set if this signature has been revoked. + // See RFC 4880, section 5.2.3.23 for details. + RevocationReason *uint8 + RevocationReasonText string + + // MDC is set if this signature has a feature packet that indicates + // support for MDC subpackets. + MDC bool + + // EmbeddedSignature, if non-nil, is a signature of the parent key, by + // this key. This prevents an attacker from claiming another's signing + // subkey as their own. + EmbeddedSignature *Signature + + outSubpackets []outputSubpacket +} + +func (sig *Signature) parse(r io.Reader) (err error) { + // RFC 4880, section 5.2.3 + var buf [5]byte + _, err = readFull(r, buf[:1]) + if err != nil { + return + } + if buf[0] != 4 { + err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) + return + } + + _, err = readFull(r, buf[:5]) + if err != nil { + return + } + sig.SigType = SignatureType(buf[0]) + sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1]) + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA: + default: + err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) + return + } + + var ok bool + sig.Hash, ok = s2k.HashIdToHash(buf[2]) + if !ok { + return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) + } + + hashedSubpacketsLength := int(buf[3])<<8 | int(buf[4]) + l := 6 + hashedSubpacketsLength + sig.HashSuffix = make([]byte, l+6) + sig.HashSuffix[0] = 4 + copy(sig.HashSuffix[1:], buf[:5]) + hashedSubpackets := sig.HashSuffix[6:l] + _, err = readFull(r, hashedSubpackets) + if err != nil { + return + } + // See RFC 4880, section 5.2.4 + trailer := sig.HashSuffix[l:] + trailer[0] = 4 + trailer[1] = 0xff + trailer[2] = uint8(l >> 24) + trailer[3] = uint8(l >> 16) + trailer[4] = uint8(l >> 8) + trailer[5] = uint8(l) + + err = parseSignatureSubpackets(sig, hashedSubpackets, true) + if err != nil { + return + } + + _, err = readFull(r, buf[:2]) + if err != nil { + return + } + unhashedSubpacketsLength := int(buf[0])<<8 | int(buf[1]) + unhashedSubpackets := make([]byte, unhashedSubpacketsLength) + _, err = readFull(r, unhashedSubpackets) + if err != nil { + return + } + err = parseSignatureSubpackets(sig, unhashedSubpackets, false) + if err != nil { + return + } + + _, err = readFull(r, sig.HashTag[:2]) + if err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) + case PubKeyAlgoDSA: + sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r) + if err == nil { + sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) + } + case PubKeyAlgoECDSA: + sig.ECDSASigR.bytes, sig.ECDSASigR.bitLength, err = readMPI(r) + if err == nil { + sig.ECDSASigS.bytes, sig.ECDSASigS.bitLength, err = readMPI(r) + } + default: + panic("unreachable") + } + return +} + +// parseSignatureSubpackets parses subpackets of the main signature packet. See +// RFC 4880, section 5.2.3.1. +func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) { + for len(subpackets) > 0 { + subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed) + if err != nil { + return + } + } + + if sig.CreationTime.IsZero() { + err = errors.StructuralError("no creation time in signature") + } + + return +} + +type signatureSubpacketType uint8 + +const ( + creationTimeSubpacket signatureSubpacketType = 2 + signatureExpirationSubpacket signatureSubpacketType = 3 + keyExpirationSubpacket signatureSubpacketType = 9 + prefSymmetricAlgosSubpacket signatureSubpacketType = 11 + issuerSubpacket signatureSubpacketType = 16 + prefHashAlgosSubpacket signatureSubpacketType = 21 + prefCompressionSubpacket signatureSubpacketType = 22 + primaryUserIdSubpacket signatureSubpacketType = 25 + keyFlagsSubpacket signatureSubpacketType = 27 + reasonForRevocationSubpacket signatureSubpacketType = 29 + featuresSubpacket signatureSubpacketType = 30 + embeddedSignatureSubpacket signatureSubpacketType = 32 +) + +// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1. +func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) { + // RFC 4880, section 5.2.3.1 + var ( + length uint32 + packetType signatureSubpacketType + isCritical bool + ) + switch { + case subpacket[0] < 192: + length = uint32(subpacket[0]) + subpacket = subpacket[1:] + case subpacket[0] < 255: + if len(subpacket) < 2 { + goto Truncated + } + length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192 + subpacket = subpacket[2:] + default: + if len(subpacket) < 5 { + goto Truncated + } + length = uint32(subpacket[1])<<24 | + uint32(subpacket[2])<<16 | + uint32(subpacket[3])<<8 | + uint32(subpacket[4]) + subpacket = subpacket[5:] + } + if length > uint32(len(subpacket)) { + goto Truncated + } + rest = subpacket[length:] + subpacket = subpacket[:length] + if len(subpacket) == 0 { + err = errors.StructuralError("zero length signature subpacket") + return + } + packetType = signatureSubpacketType(subpacket[0] & 0x7f) + isCritical = subpacket[0]&0x80 == 0x80 + subpacket = subpacket[1:] + sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket}) + switch packetType { + case creationTimeSubpacket: + if !isHashed { + err = errors.StructuralError("signature creation time in non-hashed area") + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("signature creation time not four bytes") + return + } + t := binary.BigEndian.Uint32(subpacket) + sig.CreationTime = time.Unix(int64(t), 0) + case signatureExpirationSubpacket: + // Signature expiration time, section 5.2.3.10 + if !isHashed { + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("expiration subpacket with bad length") + return + } + sig.SigLifetimeSecs = new(uint32) + *sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket) + case keyExpirationSubpacket: + // Key expiration time, section 5.2.3.6 + if !isHashed { + return + } + if len(subpacket) != 4 { + err = errors.StructuralError("key expiration subpacket with bad length") + return + } + sig.KeyLifetimeSecs = new(uint32) + *sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket) + case prefSymmetricAlgosSubpacket: + // Preferred symmetric algorithms, section 5.2.3.7 + if !isHashed { + return + } + sig.PreferredSymmetric = make([]byte, len(subpacket)) + copy(sig.PreferredSymmetric, subpacket) + case issuerSubpacket: + // Issuer, section 5.2.3.5 + if len(subpacket) != 8 { + err = errors.StructuralError("issuer subpacket with bad length") + return + } + sig.IssuerKeyId = new(uint64) + *sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket) + case prefHashAlgosSubpacket: + // Preferred hash algorithms, section 5.2.3.8 + if !isHashed { + return + } + sig.PreferredHash = make([]byte, len(subpacket)) + copy(sig.PreferredHash, subpacket) + case prefCompressionSubpacket: + // Preferred compression algorithms, section 5.2.3.9 + if !isHashed { + return + } + sig.PreferredCompression = make([]byte, len(subpacket)) + copy(sig.PreferredCompression, subpacket) + case primaryUserIdSubpacket: + // Primary User ID, section 5.2.3.19 + if !isHashed { + return + } + if len(subpacket) != 1 { + err = errors.StructuralError("primary user id subpacket with bad length") + return + } + sig.IsPrimaryId = new(bool) + if subpacket[0] > 0 { + *sig.IsPrimaryId = true + } + case keyFlagsSubpacket: + // Key flags, section 5.2.3.21 + if !isHashed { + return + } + if len(subpacket) == 0 { + err = errors.StructuralError("empty key flags subpacket") + return + } + sig.FlagsValid = true + if subpacket[0]&KeyFlagCertify != 0 { + sig.FlagCertify = true + } + if subpacket[0]&KeyFlagSign != 0 { + sig.FlagSign = true + } + if subpacket[0]&KeyFlagEncryptCommunications != 0 { + sig.FlagEncryptCommunications = true + } + if subpacket[0]&KeyFlagEncryptStorage != 0 { + sig.FlagEncryptStorage = true + } + case reasonForRevocationSubpacket: + // Reason For Revocation, section 5.2.3.23 + if !isHashed { + return + } + if len(subpacket) == 0 { + err = errors.StructuralError("empty revocation reason subpacket") + return + } + sig.RevocationReason = new(uint8) + *sig.RevocationReason = subpacket[0] + sig.RevocationReasonText = string(subpacket[1:]) + case featuresSubpacket: + // Features subpacket, section 5.2.3.24 specifies a very general + // mechanism for OpenPGP implementations to signal support for new + // features. In practice, the subpacket is used exclusively to + // indicate support for MDC-protected encryption. + sig.MDC = len(subpacket) >= 1 && subpacket[0]&1 == 1 + case embeddedSignatureSubpacket: + // Only usage is in signatures that cross-certify + // signing subkeys. section 5.2.3.26 describes the + // format, with its usage described in section 11.1 + if sig.EmbeddedSignature != nil { + err = errors.StructuralError("Cannot have multiple embedded signatures") + return + } + sig.EmbeddedSignature = new(Signature) + // Embedded signatures are required to be v4 signatures see + // section 12.1. However, we only parse v4 signatures in this + // file anyway. + if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil { + return nil, err + } + if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding { + return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType))) + } + default: + if isCritical { + err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType))) + return + } + } + return + +Truncated: + err = errors.StructuralError("signature subpacket truncated") + return +} + +// subpacketLengthLength returns the length, in bytes, of an encoded length value. +func subpacketLengthLength(length int) int { + if length < 192 { + return 1 + } + if length < 16320 { + return 2 + } + return 5 +} + +// serializeSubpacketLength marshals the given length into to. +func serializeSubpacketLength(to []byte, length int) int { + // RFC 4880, Section 4.2.2. + if length < 192 { + to[0] = byte(length) + return 1 + } + if length < 16320 { + length -= 192 + to[0] = byte((length >> 8) + 192) + to[1] = byte(length) + return 2 + } + to[0] = 255 + to[1] = byte(length >> 24) + to[2] = byte(length >> 16) + to[3] = byte(length >> 8) + to[4] = byte(length) + return 5 +} + +// subpacketsLength returns the serialized length, in bytes, of the given +// subpackets. +func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) { + for _, subpacket := range subpackets { + if subpacket.hashed == hashed { + length += subpacketLengthLength(len(subpacket.contents) + 1) + length += 1 // type byte + length += len(subpacket.contents) + } + } + return +} + +// serializeSubpackets marshals the given subpackets into to. +func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) { + for _, subpacket := range subpackets { + if subpacket.hashed == hashed { + n := serializeSubpacketLength(to, len(subpacket.contents)+1) + to[n] = byte(subpacket.subpacketType) + to = to[1+n:] + n = copy(to, subpacket.contents) + to = to[n:] + } + } + return +} + +// KeyExpired returns whether sig is a self-signature of a key that has +// expired. +func (sig *Signature) KeyExpired(currentTime time.Time) bool { + if sig.KeyLifetimeSecs == nil { + return false + } + expiry := sig.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second) + return currentTime.After(expiry) +} + +// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing. +func (sig *Signature) buildHashSuffix() (err error) { + hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true) + + var ok bool + l := 6 + hashedSubpacketsLen + sig.HashSuffix = make([]byte, l+6) + sig.HashSuffix[0] = 4 + sig.HashSuffix[1] = uint8(sig.SigType) + sig.HashSuffix[2] = uint8(sig.PubKeyAlgo) + sig.HashSuffix[3], ok = s2k.HashToHashId(sig.Hash) + if !ok { + sig.HashSuffix = nil + return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash))) + } + sig.HashSuffix[4] = byte(hashedSubpacketsLen >> 8) + sig.HashSuffix[5] = byte(hashedSubpacketsLen) + serializeSubpackets(sig.HashSuffix[6:l], sig.outSubpackets, true) + trailer := sig.HashSuffix[l:] + trailer[0] = 4 + trailer[1] = 0xff + trailer[2] = byte(l >> 24) + trailer[3] = byte(l >> 16) + trailer[4] = byte(l >> 8) + trailer[5] = byte(l) + return +} + +func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) { + err = sig.buildHashSuffix() + if err != nil { + return + } + + h.Write(sig.HashSuffix) + digest = h.Sum(nil) + copy(sig.HashTag[:], digest) + return +} + +// Sign signs a message with a private key. The hash, h, must contain +// the hash of the message to be signed and will be mutated by this function. +// On success, the signature is stored in sig. Call Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) { + sig.outSubpackets = sig.buildSubpackets() + digest, err := sig.signPrepareHash(h) + if err != nil { + return + } + + switch priv.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + // supports both *rsa.PrivateKey and crypto.Signer + sig.RSASignature.bytes, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) + sig.RSASignature.bitLength = uint16(8 * len(sig.RSASignature.bytes)) + case PubKeyAlgoDSA: + dsaPriv := priv.PrivateKey.(*dsa.PrivateKey) + + // Need to truncate hashBytes to match FIPS 186-3 section 4.6. + subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8 + if len(digest) > subgroupSize { + digest = digest[:subgroupSize] + } + r, s, err := dsa.Sign(config.Random(), dsaPriv, digest) + if err == nil { + sig.DSASigR.bytes = r.Bytes() + sig.DSASigR.bitLength = uint16(8 * len(sig.DSASigR.bytes)) + sig.DSASigS.bytes = s.Bytes() + sig.DSASigS.bitLength = uint16(8 * len(sig.DSASigS.bytes)) + } + case PubKeyAlgoECDSA: + var r, s *big.Int + if pk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok { + // direct support, avoid asn1 wrapping/unwrapping + r, s, err = ecdsa.Sign(config.Random(), pk, digest) + } else { + var b []byte + b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash) + if err == nil { + r, s, err = unwrapECDSASig(b) + } + } + if err == nil { + sig.ECDSASigR = fromBig(r) + sig.ECDSASigS = fromBig(s) + } + default: + err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo))) + } + + return +} + +// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA +// signature. +func unwrapECDSASig(b []byte) (r, s *big.Int, err error) { + var ecsdaSig struct { + R, S *big.Int + } + _, err = asn1.Unmarshal(b, &ecsdaSig) + if err != nil { + return + } + return ecsdaSig.R, ecsdaSig.S, nil +} + +// SignUserId computes a signature from priv, asserting that pub is a valid +// key for the identity id. On success, the signature is stored in sig. Call +// Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error { + h, err := userIdSignatureHash(id, pub, sig.Hash) + if err != nil { + return err + } + return sig.Sign(h, priv, config) +} + +// SignKey computes a signature from priv, asserting that pub is a subkey. On +// success, the signature is stored in sig. Call Serialize to write it out. +// If config is nil, sensible defaults will be used. +func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error { + h, err := keySignatureHash(&priv.PublicKey, pub, sig.Hash) + if err != nil { + return err + } + return sig.Sign(h, priv, config) +} + +// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been +// called first. +func (sig *Signature) Serialize(w io.Writer) (err error) { + if len(sig.outSubpackets) == 0 { + sig.outSubpackets = sig.rawSubpackets + } + if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil && sig.ECDSASigR.bytes == nil { + return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") + } + + sigLength := 0 + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sigLength = 2 + len(sig.RSASignature.bytes) + case PubKeyAlgoDSA: + sigLength = 2 + len(sig.DSASigR.bytes) + sigLength += 2 + len(sig.DSASigS.bytes) + case PubKeyAlgoECDSA: + sigLength = 2 + len(sig.ECDSASigR.bytes) + sigLength += 2 + len(sig.ECDSASigS.bytes) + default: + panic("impossible") + } + + unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false) + length := len(sig.HashSuffix) - 6 /* trailer not included */ + + 2 /* length of unhashed subpackets */ + unhashedSubpacketsLen + + 2 /* hash tag */ + sigLength + err = serializeHeader(w, packetTypeSignature, length) + if err != nil { + return + } + + _, err = w.Write(sig.HashSuffix[:len(sig.HashSuffix)-6]) + if err != nil { + return + } + + unhashedSubpackets := make([]byte, 2+unhashedSubpacketsLen) + unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8) + unhashedSubpackets[1] = byte(unhashedSubpacketsLen) + serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false) + + _, err = w.Write(unhashedSubpackets) + if err != nil { + return + } + _, err = w.Write(sig.HashTag[:]) + if err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + err = writeMPIs(w, sig.RSASignature) + case PubKeyAlgoDSA: + err = writeMPIs(w, sig.DSASigR, sig.DSASigS) + case PubKeyAlgoECDSA: + err = writeMPIs(w, sig.ECDSASigR, sig.ECDSASigS) + default: + panic("impossible") + } + return +} + +// outputSubpacket represents a subpacket to be marshaled. +type outputSubpacket struct { + hashed bool // true if this subpacket is in the hashed area. + subpacketType signatureSubpacketType + isCritical bool + contents []byte +} + +func (sig *Signature) buildSubpackets() (subpackets []outputSubpacket) { + creationTime := make([]byte, 4) + binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix())) + subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, false, creationTime}) + + if sig.IssuerKeyId != nil { + keyId := make([]byte, 8) + binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId) + subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, false, keyId}) + } + + if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 { + sigLifetime := make([]byte, 4) + binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs) + subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime}) + } + + // Key flags may only appear in self-signatures or certification signatures. + + if sig.FlagsValid { + var flags byte + if sig.FlagCertify { + flags |= KeyFlagCertify + } + if sig.FlagSign { + flags |= KeyFlagSign + } + if sig.FlagEncryptCommunications { + flags |= KeyFlagEncryptCommunications + } + if sig.FlagEncryptStorage { + flags |= KeyFlagEncryptStorage + } + subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, false, []byte{flags}}) + } + + // The following subpackets may only appear in self-signatures + + if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 { + keyLifetime := make([]byte, 4) + binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs) + subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime}) + } + + if sig.IsPrimaryId != nil && *sig.IsPrimaryId { + subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}}) + } + + if len(sig.PreferredSymmetric) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric}) + } + + if len(sig.PreferredHash) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash}) + } + + if len(sig.PreferredCompression) > 0 { + subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression}) + } + + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go new file mode 100644 index 0000000000..6edff88934 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/signature_v3.go @@ -0,0 +1,146 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto" + "encoding/binary" + "fmt" + "io" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" +) + +// SignatureV3 represents older version 3 signatures. These signatures are less secure +// than version 4 and should not be used to create new signatures. They are included +// here for backwards compatibility to read and validate with older key material. +// See RFC 4880, section 5.2.2. +type SignatureV3 struct { + SigType SignatureType + CreationTime time.Time + IssuerKeyId uint64 + PubKeyAlgo PublicKeyAlgorithm + Hash crypto.Hash + HashTag [2]byte + + RSASignature parsedMPI + DSASigR, DSASigS parsedMPI +} + +func (sig *SignatureV3) parse(r io.Reader) (err error) { + // RFC 4880, section 5.2.2 + var buf [8]byte + if _, err = readFull(r, buf[:1]); err != nil { + return + } + if buf[0] < 2 || buf[0] > 3 { + err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0]))) + return + } + if _, err = readFull(r, buf[:1]); err != nil { + return + } + if buf[0] != 5 { + err = errors.UnsupportedError( + "invalid hashed material length " + strconv.Itoa(int(buf[0]))) + return + } + + // Read hashed material: signature type + creation time + if _, err = readFull(r, buf[:5]); err != nil { + return + } + sig.SigType = SignatureType(buf[0]) + t := binary.BigEndian.Uint32(buf[1:5]) + sig.CreationTime = time.Unix(int64(t), 0) + + // Eight-octet Key ID of signer. + if _, err = readFull(r, buf[:8]); err != nil { + return + } + sig.IssuerKeyId = binary.BigEndian.Uint64(buf[:]) + + // Public-key and hash algorithm + if _, err = readFull(r, buf[:2]); err != nil { + return + } + sig.PubKeyAlgo = PublicKeyAlgorithm(buf[0]) + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA: + default: + err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo))) + return + } + var ok bool + if sig.Hash, ok = s2k.HashIdToHash(buf[1]); !ok { + return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2]))) + } + + // Two-octet field holding left 16 bits of signed hash value. + if _, err = readFull(r, sig.HashTag[:2]); err != nil { + return + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + sig.RSASignature.bytes, sig.RSASignature.bitLength, err = readMPI(r) + case PubKeyAlgoDSA: + if sig.DSASigR.bytes, sig.DSASigR.bitLength, err = readMPI(r); err != nil { + return + } + sig.DSASigS.bytes, sig.DSASigS.bitLength, err = readMPI(r) + default: + panic("unreachable") + } + return +} + +// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been +// called first. +func (sig *SignatureV3) Serialize(w io.Writer) (err error) { + buf := make([]byte, 8) + + // Write the sig type and creation time + buf[0] = byte(sig.SigType) + binary.BigEndian.PutUint32(buf[1:5], uint32(sig.CreationTime.Unix())) + if _, err = w.Write(buf[:5]); err != nil { + return + } + + // Write the issuer long key ID + binary.BigEndian.PutUint64(buf[:8], sig.IssuerKeyId) + if _, err = w.Write(buf[:8]); err != nil { + return + } + + // Write public key algorithm, hash ID, and hash value + buf[0] = byte(sig.PubKeyAlgo) + hashId, ok := s2k.HashToHashId(sig.Hash) + if !ok { + return errors.UnsupportedError(fmt.Sprintf("hash function %v", sig.Hash)) + } + buf[1] = hashId + copy(buf[2:4], sig.HashTag[:]) + if _, err = w.Write(buf[:4]); err != nil { + return + } + + if sig.RSASignature.bytes == nil && sig.DSASigR.bytes == nil { + return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize") + } + + switch sig.PubKeyAlgo { + case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly: + err = writeMPIs(w, sig.RSASignature) + case PubKeyAlgoDSA: + err = writeMPIs(w, sig.DSASigR, sig.DSASigS) + default: + panic("impossible") + } + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go new file mode 100644 index 0000000000..744c2d2c42 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetric_key_encrypted.go @@ -0,0 +1,155 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "crypto/cipher" + "io" + "strconv" + + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/s2k" +) + +// This is the largest session key that we'll support. Since no 512-bit cipher +// has even been seriously used, this is comfortably large. +const maxSessionKeySizeInBytes = 64 + +// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC +// 4880, section 5.3. +type SymmetricKeyEncrypted struct { + CipherFunc CipherFunction + s2k func(out, in []byte) + encryptedKey []byte +} + +const symmetricKeyEncryptedVersion = 4 + +func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error { + // RFC 4880, section 5.3. + var buf [2]byte + if _, err := readFull(r, buf[:]); err != nil { + return err + } + if buf[0] != symmetricKeyEncryptedVersion { + return errors.UnsupportedError("SymmetricKeyEncrypted version") + } + ske.CipherFunc = CipherFunction(buf[1]) + + if ske.CipherFunc.KeySize() == 0 { + return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[1]))) + } + + var err error + ske.s2k, err = s2k.Parse(r) + if err != nil { + return err + } + + encryptedKey := make([]byte, maxSessionKeySizeInBytes) + // The session key may follow. We just have to try and read to find + // out. If it exists then we limit it to maxSessionKeySizeInBytes. + n, err := readFull(r, encryptedKey) + if err != nil && err != io.ErrUnexpectedEOF { + return err + } + + if n != 0 { + if n == maxSessionKeySizeInBytes { + return errors.UnsupportedError("oversized encrypted session key") + } + ske.encryptedKey = encryptedKey[:n] + } + + return nil +} + +// Decrypt attempts to decrypt an encrypted session key and returns the key and +// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data +// packet. +func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) { + key := make([]byte, ske.CipherFunc.KeySize()) + ske.s2k(key, passphrase) + + if len(ske.encryptedKey) == 0 { + return key, ske.CipherFunc, nil + } + + // the IV is all zeros + iv := make([]byte, ske.CipherFunc.blockSize()) + c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv) + plaintextKey := make([]byte, len(ske.encryptedKey)) + c.XORKeyStream(plaintextKey, ske.encryptedKey) + cipherFunc := CipherFunction(plaintextKey[0]) + if cipherFunc.blockSize() == 0 { + return nil, ske.CipherFunc, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + plaintextKey = plaintextKey[1:] + if l, cipherKeySize := len(plaintextKey), cipherFunc.KeySize(); l != cipherFunc.KeySize() { + return nil, cipherFunc, errors.StructuralError("length of decrypted key (" + strconv.Itoa(l) + ") " + + "not equal to cipher keysize (" + strconv.Itoa(cipherKeySize) + ")") + } + return plaintextKey, cipherFunc, nil +} + +// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w. The +// packet contains a random session key, encrypted by a key derived from the +// given passphrase. The session key is returned and must be passed to +// SerializeSymmetricallyEncrypted. +// If config is nil, sensible defaults will be used. +func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) { + cipherFunc := config.Cipher() + keySize := cipherFunc.KeySize() + if keySize == 0 { + return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(cipherFunc))) + } + + s2kBuf := new(bytes.Buffer) + keyEncryptingKey := make([]byte, keySize) + // s2k.Serialize salts and stretches the passphrase, and writes the + // resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf. + err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, &s2k.Config{Hash: config.Hash(), S2KCount: config.PasswordHashIterations()}) + if err != nil { + return + } + s2kBytes := s2kBuf.Bytes() + + packetLength := 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize + err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength) + if err != nil { + return + } + + var buf [2]byte + buf[0] = symmetricKeyEncryptedVersion + buf[1] = byte(cipherFunc) + _, err = w.Write(buf[:]) + if err != nil { + return + } + _, err = w.Write(s2kBytes) + if err != nil { + return + } + + sessionKey := make([]byte, keySize) + _, err = io.ReadFull(config.Random(), sessionKey) + if err != nil { + return + } + iv := make([]byte, cipherFunc.blockSize()) + c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv) + encryptedCipherAndKey := make([]byte, keySize+1) + c.XORKeyStream(encryptedCipherAndKey, buf[1:]) + c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey) + _, err = w.Write(encryptedCipherAndKey) + if err != nil { + return + } + + key = sessionKey + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go new file mode 100644 index 0000000000..1a1a62964f --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/symmetrically_encrypted.go @@ -0,0 +1,290 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "crypto/cipher" + "crypto/sha1" + "crypto/subtle" + "golang.org/x/crypto/openpgp/errors" + "hash" + "io" + "strconv" +) + +// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The +// encrypted contents will consist of more OpenPGP packets. See RFC 4880, +// sections 5.7 and 5.13. +type SymmetricallyEncrypted struct { + MDC bool // true iff this is a type 18 packet and thus has an embedded MAC. + contents io.Reader + prefix []byte +} + +const symmetricallyEncryptedVersion = 1 + +func (se *SymmetricallyEncrypted) parse(r io.Reader) error { + if se.MDC { + // See RFC 4880, section 5.13. + var buf [1]byte + _, err := readFull(r, buf[:]) + if err != nil { + return err + } + if buf[0] != symmetricallyEncryptedVersion { + return errors.UnsupportedError("unknown SymmetricallyEncrypted version") + } + } + se.contents = r + return nil +} + +// Decrypt returns a ReadCloser, from which the decrypted contents of the +// packet can be read. An incorrect key can, with high probability, be detected +// immediately and this will result in a KeyIncorrect error being returned. +func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) { + keySize := c.KeySize() + if keySize == 0 { + return nil, errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(c))) + } + if len(key) != keySize { + return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length") + } + + if se.prefix == nil { + se.prefix = make([]byte, c.blockSize()+2) + _, err := readFull(se.contents, se.prefix) + if err != nil { + return nil, err + } + } else if len(se.prefix) != c.blockSize()+2 { + return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths") + } + + ocfbResync := OCFBResync + if se.MDC { + // MDC packets use a different form of OCFB mode. + ocfbResync = OCFBNoResync + } + + s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync) + if s == nil { + return nil, errors.ErrKeyIncorrect + } + + plaintext := cipher.StreamReader{S: s, R: se.contents} + + if se.MDC { + // MDC packets have an embedded hash that we need to check. + h := sha1.New() + h.Write(se.prefix) + return &seMDCReader{in: plaintext, h: h}, nil + } + + // Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser. + return seReader{plaintext}, nil +} + +// seReader wraps an io.Reader with a no-op Close method. +type seReader struct { + in io.Reader +} + +func (ser seReader) Read(buf []byte) (int, error) { + return ser.in.Read(buf) +} + +func (ser seReader) Close() error { + return nil +} + +const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size + +// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold +// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an +// MDC packet containing a hash of the previous contents which is checked +// against the running hash. See RFC 4880, section 5.13. +type seMDCReader struct { + in io.Reader + h hash.Hash + trailer [mdcTrailerSize]byte + scratch [mdcTrailerSize]byte + trailerUsed int + error bool + eof bool +} + +func (ser *seMDCReader) Read(buf []byte) (n int, err error) { + if ser.error { + err = io.ErrUnexpectedEOF + return + } + if ser.eof { + err = io.EOF + return + } + + // If we haven't yet filled the trailer buffer then we must do that + // first. + for ser.trailerUsed < mdcTrailerSize { + n, err = ser.in.Read(ser.trailer[ser.trailerUsed:]) + ser.trailerUsed += n + if err == io.EOF { + if ser.trailerUsed != mdcTrailerSize { + n = 0 + err = io.ErrUnexpectedEOF + ser.error = true + return + } + ser.eof = true + n = 0 + return + } + + if err != nil { + n = 0 + return + } + } + + // If it's a short read then we read into a temporary buffer and shift + // the data into the caller's buffer. + if len(buf) <= mdcTrailerSize { + n, err = readFull(ser.in, ser.scratch[:len(buf)]) + copy(buf, ser.trailer[:n]) + ser.h.Write(buf[:n]) + copy(ser.trailer[:], ser.trailer[n:]) + copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:]) + if n < len(buf) { + ser.eof = true + err = io.EOF + } + return + } + + n, err = ser.in.Read(buf[mdcTrailerSize:]) + copy(buf, ser.trailer[:]) + ser.h.Write(buf[:n]) + copy(ser.trailer[:], buf[n:]) + + if err == io.EOF { + ser.eof = true + } + return +} + +// This is a new-format packet tag byte for a type 19 (MDC) packet. +const mdcPacketTagByte = byte(0x80) | 0x40 | 19 + +func (ser *seMDCReader) Close() error { + if ser.error { + return errors.SignatureError("error during reading") + } + + for !ser.eof { + // We haven't seen EOF so we need to read to the end + var buf [1024]byte + _, err := ser.Read(buf[:]) + if err == io.EOF { + break + } + if err != nil { + return errors.SignatureError("error during reading") + } + } + + if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size { + return errors.SignatureError("MDC packet not found") + } + ser.h.Write(ser.trailer[:2]) + + final := ser.h.Sum(nil) + if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 { + return errors.SignatureError("hash mismatch") + } + return nil +} + +// An seMDCWriter writes through to an io.WriteCloser while maintains a running +// hash of the data written. On close, it emits an MDC packet containing the +// running hash. +type seMDCWriter struct { + w io.WriteCloser + h hash.Hash +} + +func (w *seMDCWriter) Write(buf []byte) (n int, err error) { + w.h.Write(buf) + return w.w.Write(buf) +} + +func (w *seMDCWriter) Close() (err error) { + var buf [mdcTrailerSize]byte + + buf[0] = mdcPacketTagByte + buf[1] = sha1.Size + w.h.Write(buf[:2]) + digest := w.h.Sum(nil) + copy(buf[2:], digest) + + _, err = w.w.Write(buf[:]) + if err != nil { + return + } + return w.w.Close() +} + +// noOpCloser is like an io.NopCloser, but for an io.Writer. +type noOpCloser struct { + w io.Writer +} + +func (c noOpCloser) Write(data []byte) (n int, err error) { + return c.w.Write(data) +} + +func (c noOpCloser) Close() error { + return nil +} + +// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet +// to w and returns a WriteCloser to which the to-be-encrypted packets can be +// written. +// If config is nil, sensible defaults will be used. +func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, key []byte, config *Config) (contents io.WriteCloser, err error) { + if c.KeySize() != len(key) { + return nil, errors.InvalidArgumentError("SymmetricallyEncrypted.Serialize: bad key length") + } + writeCloser := noOpCloser{w} + ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedMDC) + if err != nil { + return + } + + _, err = ciphertext.Write([]byte{symmetricallyEncryptedVersion}) + if err != nil { + return + } + + block := c.new(key) + blockSize := block.BlockSize() + iv := make([]byte, blockSize) + _, err = config.Random().Read(iv) + if err != nil { + return + } + s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync) + _, err = ciphertext.Write(prefix) + if err != nil { + return + } + plaintext := cipher.StreamWriter{S: s, W: ciphertext} + + h := sha1.New() + h.Write(iv) + h.Write(iv[blockSize-2:]) + contents = &seMDCWriter{w: plaintext, h: h} + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go new file mode 100644 index 0000000000..ff7ef53075 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/userattribute.go @@ -0,0 +1,90 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "bytes" + "image" + "image/jpeg" + "io" +) + +const UserAttrImageSubpacket = 1 + +// UserAttribute is capable of storing other types of data about a user +// beyond name, email and a text comment. In practice, user attributes are typically used +// to store a signed thumbnail photo JPEG image of the user. +// See RFC 4880, section 5.12. +type UserAttribute struct { + Contents []*OpaqueSubpacket +} + +// NewUserAttributePhoto creates a user attribute packet +// containing the given images. +func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) { + uat = new(UserAttribute) + for _, photo := range photos { + var buf bytes.Buffer + // RFC 4880, Section 5.12.1. + data := []byte{ + 0x10, 0x00, // Little-endian image header length (16 bytes) + 0x01, // Image header version 1 + 0x01, // JPEG + 0, 0, 0, 0, // 12 reserved octets, must be all zero. + 0, 0, 0, 0, + 0, 0, 0, 0} + if _, err = buf.Write(data); err != nil { + return + } + if err = jpeg.Encode(&buf, photo, nil); err != nil { + return + } + uat.Contents = append(uat.Contents, &OpaqueSubpacket{ + SubType: UserAttrImageSubpacket, + Contents: buf.Bytes()}) + } + return +} + +// NewUserAttribute creates a new user attribute packet containing the given subpackets. +func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute { + return &UserAttribute{Contents: contents} +} + +func (uat *UserAttribute) parse(r io.Reader) (err error) { + // RFC 4880, section 5.13 + b, err := io.ReadAll(r) + if err != nil { + return + } + uat.Contents, err = OpaqueSubpackets(b) + return +} + +// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including +// header. +func (uat *UserAttribute) Serialize(w io.Writer) (err error) { + var buf bytes.Buffer + for _, sp := range uat.Contents { + sp.Serialize(&buf) + } + if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil { + return err + } + _, err = w.Write(buf.Bytes()) + return +} + +// ImageData returns zero or more byte slices, each containing +// JPEG File Interchange Format (JFIF), for each photo in the +// user attribute packet. +func (uat *UserAttribute) ImageData() (imageData [][]byte) { + for _, sp := range uat.Contents { + if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 { + imageData = append(imageData, sp.Contents[16:]) + } + } + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/packet/userid.go b/vendor/golang.org/x/crypto/openpgp/packet/userid.go new file mode 100644 index 0000000000..359a462eb8 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/packet/userid.go @@ -0,0 +1,159 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package packet + +import ( + "io" + "strings" +) + +// UserId contains text that is intended to represent the name and email +// address of the key holder. See RFC 4880, section 5.11. By convention, this +// takes the form "Full Name (Comment) " +type UserId struct { + Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below. + + Name, Comment, Email string +} + +func hasInvalidCharacters(s string) bool { + for _, c := range s { + switch c { + case '(', ')', '<', '>', 0: + return true + } + } + return false +} + +// NewUserId returns a UserId or nil if any of the arguments contain invalid +// characters. The invalid characters are '\x00', '(', ')', '<' and '>' +func NewUserId(name, comment, email string) *UserId { + // RFC 4880 doesn't deal with the structure of userid strings; the + // name, comment and email form is just a convention. However, there's + // no convention about escaping the metacharacters and GPG just refuses + // to create user ids where, say, the name contains a '('. We mirror + // this behaviour. + + if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) { + return nil + } + + uid := new(UserId) + uid.Name, uid.Comment, uid.Email = name, comment, email + uid.Id = name + if len(comment) > 0 { + if len(uid.Id) > 0 { + uid.Id += " " + } + uid.Id += "(" + uid.Id += comment + uid.Id += ")" + } + if len(email) > 0 { + if len(uid.Id) > 0 { + uid.Id += " " + } + uid.Id += "<" + uid.Id += email + uid.Id += ">" + } + return uid +} + +func (uid *UserId) parse(r io.Reader) (err error) { + // RFC 4880, section 5.11 + b, err := io.ReadAll(r) + if err != nil { + return + } + uid.Id = string(b) + uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id) + return +} + +// Serialize marshals uid to w in the form of an OpenPGP packet, including +// header. +func (uid *UserId) Serialize(w io.Writer) error { + err := serializeHeader(w, packetTypeUserId, len(uid.Id)) + if err != nil { + return err + } + _, err = w.Write([]byte(uid.Id)) + return err +} + +// parseUserId extracts the name, comment and email from a user id string that +// is formatted as "Full Name (Comment) ". +func parseUserId(id string) (name, comment, email string) { + var n, c, e struct { + start, end int + } + var state int + + for offset, rune := range id { + switch state { + case 0: + // Entering name + n.start = offset + state = 1 + fallthrough + case 1: + // In name + if rune == '(' { + state = 2 + n.end = offset + } else if rune == '<' { + state = 5 + n.end = offset + } + case 2: + // Entering comment + c.start = offset + state = 3 + fallthrough + case 3: + // In comment + if rune == ')' { + state = 4 + c.end = offset + } + case 4: + // Between comment and email + if rune == '<' { + state = 5 + } + case 5: + // Entering email + e.start = offset + state = 6 + fallthrough + case 6: + // In email + if rune == '>' { + state = 7 + e.end = offset + } + default: + // After email + } + } + switch state { + case 1: + // ended in the name + n.end = len(id) + case 3: + // ended in comment + c.end = len(id) + case 6: + // ended in email + e.end = len(id) + } + + name = strings.TrimSpace(id[n.start:n.end]) + comment = strings.TrimSpace(id[c.start:c.end]) + email = strings.TrimSpace(id[e.start:e.end]) + return +} diff --git a/vendor/golang.org/x/crypto/openpgp/read.go b/vendor/golang.org/x/crypto/openpgp/read.go new file mode 100644 index 0000000000..cff3db9196 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/read.go @@ -0,0 +1,448 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package openpgp implements high level operations on OpenPGP messages. +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package openpgp + +import ( + "crypto" + _ "crypto/sha256" + "hash" + "io" + "strconv" + + "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/packet" +) + +// SignatureType is the armor type for a PGP signature. +var SignatureType = "PGP SIGNATURE" + +// readArmored reads an armored block with the given type. +func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) { + block, err := armor.Decode(r) + if err != nil { + return + } + + if block.Type != expectedType { + return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type) + } + + return block.Body, nil +} + +// MessageDetails contains the result of parsing an OpenPGP encrypted and/or +// signed message. +type MessageDetails struct { + IsEncrypted bool // true if the message was encrypted. + EncryptedToKeyIds []uint64 // the list of recipient key ids. + IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message. + DecryptedWith Key // the private key used to decrypt the message, if any. + IsSigned bool // true if the message is signed. + SignedByKeyId uint64 // the key id of the signer, if any. + SignedBy *Key // the key of the signer, if available. + LiteralData *packet.LiteralData // the metadata of the contents + UnverifiedBody io.Reader // the contents of the message. + + // If IsSigned is true and SignedBy is non-zero then the signature will + // be verified as UnverifiedBody is read. The signature cannot be + // checked until the whole of UnverifiedBody is read so UnverifiedBody + // must be consumed until EOF before the data can be trusted. Even if a + // message isn't signed (or the signer is unknown) the data may contain + // an authentication code that is only checked once UnverifiedBody has + // been consumed. Once EOF has been seen, the following fields are + // valid. (An authentication code failure is reported as a + // SignatureError error when reading from UnverifiedBody.) + SignatureError error // nil if the signature is good. + Signature *packet.Signature // the signature packet itself, if v4 (default) + SignatureV3 *packet.SignatureV3 // the signature packet if it is a v2 or v3 signature + + decrypted io.ReadCloser +} + +// A PromptFunction is used as a callback by functions that may need to decrypt +// a private key, or prompt for a passphrase. It is called with a list of +// acceptable, encrypted private keys and a boolean that indicates whether a +// passphrase is usable. It should either decrypt a private key or return a +// passphrase to try. If the decrypted private key or given passphrase isn't +// correct, the function will be called again, forever. Any error returned will +// be passed up. +type PromptFunction func(keys []Key, symmetric bool) ([]byte, error) + +// A keyEnvelopePair is used to store a private key with the envelope that +// contains a symmetric key, encrypted with that key. +type keyEnvelopePair struct { + key Key + encryptedKey *packet.EncryptedKey +} + +// ReadMessage parses an OpenPGP message that may be signed and/or encrypted. +// The given KeyRing should contain both public keys (for signature +// verification) and, possibly encrypted, private keys for decrypting. +// If config is nil, sensible defaults will be used. +func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) { + var p packet.Packet + + var symKeys []*packet.SymmetricKeyEncrypted + var pubKeys []keyEnvelopePair + var se *packet.SymmetricallyEncrypted + + packets := packet.NewReader(r) + md = new(MessageDetails) + md.IsEncrypted = true + + // The message, if encrypted, starts with a number of packets + // containing an encrypted decryption key. The decryption key is either + // encrypted to a public key, or with a passphrase. This loop + // collects these packets. +ParsePackets: + for { + p, err = packets.Next() + if err != nil { + return nil, err + } + switch p := p.(type) { + case *packet.SymmetricKeyEncrypted: + // This packet contains the decryption key encrypted with a passphrase. + md.IsSymmetricallyEncrypted = true + symKeys = append(symKeys, p) + case *packet.EncryptedKey: + // This packet contains the decryption key encrypted to a public key. + md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId) + switch p.Algo { + case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal: + break + default: + continue + } + var keys []Key + if p.KeyId == 0 { + keys = keyring.DecryptionKeys() + } else { + keys = keyring.KeysById(p.KeyId) + } + for _, k := range keys { + pubKeys = append(pubKeys, keyEnvelopePair{k, p}) + } + case *packet.SymmetricallyEncrypted: + se = p + break ParsePackets + case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature: + // This message isn't encrypted. + if len(symKeys) != 0 || len(pubKeys) != 0 { + return nil, errors.StructuralError("key material not followed by encrypted message") + } + packets.Unread(p) + return readSignedMessage(packets, nil, keyring) + } + } + + var candidates []Key + var decrypted io.ReadCloser + + // Now that we have the list of encrypted keys we need to decrypt at + // least one of them or, if we cannot, we need to call the prompt + // function so that it can decrypt a key or give us a passphrase. +FindKey: + for { + // See if any of the keys already have a private key available + candidates = candidates[:0] + candidateFingerprints := make(map[string]bool) + + for _, pk := range pubKeys { + if pk.key.PrivateKey == nil { + continue + } + if !pk.key.PrivateKey.Encrypted { + if len(pk.encryptedKey.Key) == 0 { + pk.encryptedKey.Decrypt(pk.key.PrivateKey, config) + } + if len(pk.encryptedKey.Key) == 0 { + continue + } + decrypted, err = se.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key) + if err != nil && err != errors.ErrKeyIncorrect { + return nil, err + } + if decrypted != nil { + md.DecryptedWith = pk.key + break FindKey + } + } else { + fpr := string(pk.key.PublicKey.Fingerprint[:]) + if v := candidateFingerprints[fpr]; v { + continue + } + candidates = append(candidates, pk.key) + candidateFingerprints[fpr] = true + } + } + + if len(candidates) == 0 && len(symKeys) == 0 { + return nil, errors.ErrKeyIncorrect + } + + if prompt == nil { + return nil, errors.ErrKeyIncorrect + } + + passphrase, err := prompt(candidates, len(symKeys) != 0) + if err != nil { + return nil, err + } + + // Try the symmetric passphrase first + if len(symKeys) != 0 && passphrase != nil { + for _, s := range symKeys { + key, cipherFunc, err := s.Decrypt(passphrase) + if err == nil { + decrypted, err = se.Decrypt(cipherFunc, key) + if err != nil && err != errors.ErrKeyIncorrect { + return nil, err + } + if decrypted != nil { + break FindKey + } + } + + } + } + } + + md.decrypted = decrypted + if err := packets.Push(decrypted); err != nil { + return nil, err + } + return readSignedMessage(packets, md, keyring) +} + +// readSignedMessage reads a possibly signed message if mdin is non-zero then +// that structure is updated and returned. Otherwise a fresh MessageDetails is +// used. +func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing) (md *MessageDetails, err error) { + if mdin == nil { + mdin = new(MessageDetails) + } + md = mdin + + var p packet.Packet + var h hash.Hash + var wrappedHash hash.Hash +FindLiteralData: + for { + p, err = packets.Next() + if err != nil { + return nil, err + } + switch p := p.(type) { + case *packet.Compressed: + if err := packets.Push(p.Body); err != nil { + return nil, err + } + case *packet.OnePassSignature: + if !p.IsLast { + return nil, errors.UnsupportedError("nested signatures") + } + + h, wrappedHash, err = hashForSignature(p.Hash, p.SigType) + if err != nil { + md = nil + return + } + + md.IsSigned = true + md.SignedByKeyId = p.KeyId + keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign) + if len(keys) > 0 { + md.SignedBy = &keys[0] + } + case *packet.LiteralData: + md.LiteralData = p + break FindLiteralData + } + } + + if md.SignedBy != nil { + md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md} + } else if md.decrypted != nil { + md.UnverifiedBody = checkReader{md} + } else { + md.UnverifiedBody = md.LiteralData.Body + } + + return md, nil +} + +// hashForSignature returns a pair of hashes that can be used to verify a +// signature. The signature may specify that the contents of the signed message +// should be preprocessed (i.e. to normalize line endings). Thus this function +// returns two hashes. The second should be used to hash the message itself and +// performs any needed preprocessing. +func hashForSignature(hashId crypto.Hash, sigType packet.SignatureType) (hash.Hash, hash.Hash, error) { + if !hashId.Available() { + return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashId))) + } + h := hashId.New() + + switch sigType { + case packet.SigTypeBinary: + return h, h, nil + case packet.SigTypeText: + return h, NewCanonicalTextHash(h), nil + } + + return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType))) +} + +// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF +// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger +// MDC checks. +type checkReader struct { + md *MessageDetails +} + +func (cr checkReader) Read(buf []byte) (n int, err error) { + n, err = cr.md.LiteralData.Body.Read(buf) + if err == io.EOF { + mdcErr := cr.md.decrypted.Close() + if mdcErr != nil { + err = mdcErr + } + } + return +} + +// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes +// the data as it is read. When it sees an EOF from the underlying io.Reader +// it parses and checks a trailing Signature packet and triggers any MDC checks. +type signatureCheckReader struct { + packets *packet.Reader + h, wrappedHash hash.Hash + md *MessageDetails +} + +func (scr *signatureCheckReader) Read(buf []byte) (n int, err error) { + n, err = scr.md.LiteralData.Body.Read(buf) + scr.wrappedHash.Write(buf[:n]) + if err == io.EOF { + var p packet.Packet + p, scr.md.SignatureError = scr.packets.Next() + if scr.md.SignatureError != nil { + return + } + + var ok bool + if scr.md.Signature, ok = p.(*packet.Signature); ok { + scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignature(scr.h, scr.md.Signature) + } else if scr.md.SignatureV3, ok = p.(*packet.SignatureV3); ok { + scr.md.SignatureError = scr.md.SignedBy.PublicKey.VerifySignatureV3(scr.h, scr.md.SignatureV3) + } else { + scr.md.SignatureError = errors.StructuralError("LiteralData not followed by Signature") + return + } + + // The SymmetricallyEncrypted packet, if any, might have an + // unsigned hash of its own. In order to check this we need to + // close that Reader. + if scr.md.decrypted != nil { + mdcErr := scr.md.decrypted.Close() + if mdcErr != nil { + err = mdcErr + } + } + } + return +} + +// CheckDetachedSignature takes a signed file and a detached signature and +// returns the signer if the signature is valid. If the signer isn't known, +// ErrUnknownIssuer is returned. +func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { + var issuerKeyId uint64 + var hashFunc crypto.Hash + var sigType packet.SignatureType + var keys []Key + var p packet.Packet + + packets := packet.NewReader(signature) + for { + p, err = packets.Next() + if err == io.EOF { + return nil, errors.ErrUnknownIssuer + } + if err != nil { + return nil, err + } + + switch sig := p.(type) { + case *packet.Signature: + if sig.IssuerKeyId == nil { + return nil, errors.StructuralError("signature doesn't have an issuer") + } + issuerKeyId = *sig.IssuerKeyId + hashFunc = sig.Hash + sigType = sig.SigType + case *packet.SignatureV3: + issuerKeyId = sig.IssuerKeyId + hashFunc = sig.Hash + sigType = sig.SigType + default: + return nil, errors.StructuralError("non signature packet found") + } + + keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign) + if len(keys) > 0 { + break + } + } + + if len(keys) == 0 { + panic("unreachable") + } + + h, wrappedHash, err := hashForSignature(hashFunc, sigType) + if err != nil { + return nil, err + } + + if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF { + return nil, err + } + + for _, key := range keys { + switch sig := p.(type) { + case *packet.Signature: + err = key.PublicKey.VerifySignature(h, sig) + case *packet.SignatureV3: + err = key.PublicKey.VerifySignatureV3(h, sig) + default: + panic("unreachable") + } + + if err == nil { + return key.Entity, nil + } + } + + return nil, err +} + +// CheckArmoredDetachedSignature performs the same actions as +// CheckDetachedSignature but expects the signature to be armored. +func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader) (signer *Entity, err error) { + body, err := readArmored(signature, SignatureType) + if err != nil { + return + } + + return CheckDetachedSignature(keyring, signed, body) +} diff --git a/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go new file mode 100644 index 0000000000..fa1a919079 --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/s2k/s2k.go @@ -0,0 +1,279 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package s2k implements the various OpenPGP string-to-key transforms as +// specified in RFC 4800 section 3.7.1. +// +// Deprecated: this package is unmaintained except for security fixes. New +// applications should consider a more focused, modern alternative to OpenPGP +// for their specific task. If you are required to interoperate with OpenPGP +// systems and need a maintained package, consider a community fork. +// See https://golang.org/issue/44226. +package s2k + +import ( + "crypto" + "hash" + "io" + "strconv" + + "golang.org/x/crypto/openpgp/errors" +) + +// Config collects configuration parameters for s2k key-stretching +// transformatioms. A nil *Config is valid and results in all default +// values. Currently, Config is used only by the Serialize function in +// this package. +type Config struct { + // Hash is the default hash function to be used. If + // nil, SHA1 is used. + Hash crypto.Hash + // S2KCount is only used for symmetric encryption. It + // determines the strength of the passphrase stretching when + // the said passphrase is hashed to produce a key. S2KCount + // should be between 1024 and 65011712, inclusive. If Config + // is nil or S2KCount is 0, the value 65536 used. Not all + // values in the above range can be represented. S2KCount will + // be rounded up to the next representable value if it cannot + // be encoded exactly. When set, it is strongly encrouraged to + // use a value that is at least 65536. See RFC 4880 Section + // 3.7.1.3. + S2KCount int +} + +func (c *Config) hash() crypto.Hash { + if c == nil || uint(c.Hash) == 0 { + // SHA1 is the historical default in this package. + return crypto.SHA1 + } + + return c.Hash +} + +func (c *Config) encodedCount() uint8 { + if c == nil || c.S2KCount == 0 { + return 96 // The common case. Correspoding to 65536 + } + + i := c.S2KCount + switch { + // Behave like GPG. Should we make 65536 the lowest value used? + case i < 1024: + i = 1024 + case i > 65011712: + i = 65011712 + } + + return encodeCount(i) +} + +// encodeCount converts an iterative "count" in the range 1024 to +// 65011712, inclusive, to an encoded count. The return value is the +// octet that is actually stored in the GPG file. encodeCount panics +// if i is not in the above range (encodedCount above takes care to +// pass i in the correct range). See RFC 4880 Section 3.7.7.1. +func encodeCount(i int) uint8 { + if i < 1024 || i > 65011712 { + panic("count arg i outside the required range") + } + + for encoded := 0; encoded < 256; encoded++ { + count := decodeCount(uint8(encoded)) + if count >= i { + return uint8(encoded) + } + } + + return 255 +} + +// decodeCount returns the s2k mode 3 iterative "count" corresponding to +// the encoded octet c. +func decodeCount(c uint8) int { + return (16 + int(c&15)) << (uint32(c>>4) + 6) +} + +// Simple writes to out the result of computing the Simple S2K function (RFC +// 4880, section 3.7.1.1) using the given hash and input passphrase. +func Simple(out []byte, h hash.Hash, in []byte) { + Salted(out, h, in, nil) +} + +var zero [1]byte + +// Salted writes to out the result of computing the Salted S2K function (RFC +// 4880, section 3.7.1.2) using the given hash, input passphrase and salt. +func Salted(out []byte, h hash.Hash, in []byte, salt []byte) { + done := 0 + var digest []byte + + for i := 0; done < len(out); i++ { + h.Reset() + for j := 0; j < i; j++ { + h.Write(zero[:]) + } + h.Write(salt) + h.Write(in) + digest = h.Sum(digest[:0]) + n := copy(out[done:], digest) + done += n + } +} + +// Iterated writes to out the result of computing the Iterated and Salted S2K +// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase, +// salt and iteration count. +func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) { + combined := make([]byte, len(in)+len(salt)) + copy(combined, salt) + copy(combined[len(salt):], in) + + if count < len(combined) { + count = len(combined) + } + + done := 0 + var digest []byte + for i := 0; done < len(out); i++ { + h.Reset() + for j := 0; j < i; j++ { + h.Write(zero[:]) + } + written := 0 + for written < count { + if written+len(combined) > count { + todo := count - written + h.Write(combined[:todo]) + written = count + } else { + h.Write(combined) + written += len(combined) + } + } + digest = h.Sum(digest[:0]) + n := copy(out[done:], digest) + done += n + } +} + +// Parse reads a binary specification for a string-to-key transformation from r +// and returns a function which performs that transform. +func Parse(r io.Reader) (f func(out, in []byte), err error) { + var buf [9]byte + + _, err = io.ReadFull(r, buf[:2]) + if err != nil { + return + } + + hash, ok := HashIdToHash(buf[1]) + if !ok { + return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(buf[1]))) + } + if !hash.Available() { + return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hash))) + } + h := hash.New() + + switch buf[0] { + case 0: + f := func(out, in []byte) { + Simple(out, h, in) + } + return f, nil + case 1: + _, err = io.ReadFull(r, buf[:8]) + if err != nil { + return + } + f := func(out, in []byte) { + Salted(out, h, in, buf[:8]) + } + return f, nil + case 3: + _, err = io.ReadFull(r, buf[:9]) + if err != nil { + return + } + count := decodeCount(buf[8]) + f := func(out, in []byte) { + Iterated(out, h, in, buf[:8], count) + } + return f, nil + } + + return nil, errors.UnsupportedError("S2K function") +} + +// Serialize salts and stretches the given passphrase and writes the +// resulting key into key. It also serializes an S2K descriptor to +// w. The key stretching can be configured with c, which may be +// nil. In that case, sensible defaults will be used. +func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error { + var buf [11]byte + buf[0] = 3 /* iterated and salted */ + buf[1], _ = HashToHashId(c.hash()) + salt := buf[2:10] + if _, err := io.ReadFull(rand, salt); err != nil { + return err + } + encodedCount := c.encodedCount() + count := decodeCount(encodedCount) + buf[10] = encodedCount + if _, err := w.Write(buf[:]); err != nil { + return err + } + + Iterated(key, c.hash().New(), passphrase, salt, count) + return nil +} + +// hashToHashIdMapping contains pairs relating OpenPGP's hash identifier with +// Go's crypto.Hash type. See RFC 4880, section 9.4. +var hashToHashIdMapping = []struct { + id byte + hash crypto.Hash + name string +}{ + {1, crypto.MD5, "MD5"}, + {2, crypto.SHA1, "SHA1"}, + {3, crypto.RIPEMD160, "RIPEMD160"}, + {8, crypto.SHA256, "SHA256"}, + {9, crypto.SHA384, "SHA384"}, + {10, crypto.SHA512, "SHA512"}, + {11, crypto.SHA224, "SHA224"}, +} + +// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP +// hash id. +func HashIdToHash(id byte) (h crypto.Hash, ok bool) { + for _, m := range hashToHashIdMapping { + if m.id == id { + return m.hash, true + } + } + return 0, false +} + +// HashIdToString returns the name of the hash function corresponding to the +// given OpenPGP hash id. +func HashIdToString(id byte) (name string, ok bool) { + for _, m := range hashToHashIdMapping { + if m.id == id { + return m.name, true + } + } + + return "", false +} + +// HashToHashId returns an OpenPGP hash id which corresponds the given Hash. +func HashToHashId(h crypto.Hash) (id byte, ok bool) { + for _, m := range hashToHashIdMapping { + if m.hash == h { + return m.id, true + } + } + return 0, false +} diff --git a/vendor/golang.org/x/crypto/openpgp/write.go b/vendor/golang.org/x/crypto/openpgp/write.go new file mode 100644 index 0000000000..b89d48b81d --- /dev/null +++ b/vendor/golang.org/x/crypto/openpgp/write.go @@ -0,0 +1,418 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package openpgp + +import ( + "crypto" + "hash" + "io" + "strconv" + "time" + + "golang.org/x/crypto/openpgp/armor" + "golang.org/x/crypto/openpgp/errors" + "golang.org/x/crypto/openpgp/packet" + "golang.org/x/crypto/openpgp/s2k" +) + +// DetachSign signs message with the private key from signer (which must +// already have been decrypted) and writes the signature to w. +// If config is nil, sensible defaults will be used. +func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return detachSign(w, signer, message, packet.SigTypeBinary, config) +} + +// ArmoredDetachSign signs message with the private key from signer (which +// must already have been decrypted) and writes an armored signature to w. +// If config is nil, sensible defaults will be used. +func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) { + return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config) +} + +// DetachSignText signs message (after canonicalising the line endings) with +// the private key from signer (which must already have been decrypted) and +// writes the signature to w. +// If config is nil, sensible defaults will be used. +func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return detachSign(w, signer, message, packet.SigTypeText, config) +} + +// ArmoredDetachSignText signs message (after canonicalising the line endings) +// with the private key from signer (which must already have been decrypted) +// and writes an armored signature to w. +// If config is nil, sensible defaults will be used. +func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error { + return armoredDetachSign(w, signer, message, packet.SigTypeText, config) +} + +func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { + out, err := armor.Encode(w, SignatureType, nil) + if err != nil { + return + } + err = detachSign(out, signer, message, sigType, config) + if err != nil { + return + } + return out.Close() +} + +func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) { + if signer.PrivateKey == nil { + return errors.InvalidArgumentError("signing key doesn't have a private key") + } + if signer.PrivateKey.Encrypted { + return errors.InvalidArgumentError("signing key is encrypted") + } + + sig := new(packet.Signature) + sig.SigType = sigType + sig.PubKeyAlgo = signer.PrivateKey.PubKeyAlgo + sig.Hash = config.Hash() + sig.CreationTime = config.Now() + sig.IssuerKeyId = &signer.PrivateKey.KeyId + + h, wrappedHash, err := hashForSignature(sig.Hash, sig.SigType) + if err != nil { + return + } + io.Copy(wrappedHash, message) + + err = sig.Sign(h, signer.PrivateKey, config) + if err != nil { + return + } + + return sig.Serialize(w) +} + +// FileHints contains metadata about encrypted files. This metadata is, itself, +// encrypted. +type FileHints struct { + // IsBinary can be set to hint that the contents are binary data. + IsBinary bool + // FileName hints at the name of the file that should be written. It's + // truncated to 255 bytes if longer. It may be empty to suggest that the + // file should not be written to disk. It may be equal to "_CONSOLE" to + // suggest the data should not be written to disk. + FileName string + // ModTime contains the modification time of the file, or the zero time if not applicable. + ModTime time.Time +} + +// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase. +// The resulting WriteCloser must be closed after the contents of the file have +// been written. +// If config is nil, sensible defaults will be used. +func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + if hints == nil { + hints = &FileHints{} + } + + key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config) + if err != nil { + return + } + w, err := packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), key, config) + if err != nil { + return + } + + literaldata := w + if algo := config.Compression(); algo != packet.CompressionNone { + var compConfig *packet.CompressionConfig + if config != nil { + compConfig = config.CompressionConfig + } + literaldata, err = packet.SerializeCompressed(w, algo, compConfig) + if err != nil { + return + } + } + + var epochSeconds uint32 + if !hints.ModTime.IsZero() { + epochSeconds = uint32(hints.ModTime.Unix()) + } + return packet.SerializeLiteral(literaldata, hints.IsBinary, hints.FileName, epochSeconds) +} + +// intersectPreferences mutates and returns a prefix of a that contains only +// the values in the intersection of a and b. The order of a is preserved. +func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) { + var j int + for _, v := range a { + for _, v2 := range b { + if v == v2 { + a[j] = v + j++ + break + } + } + } + + return a[:j] +} + +func hashToHashId(h crypto.Hash) uint8 { + v, ok := s2k.HashToHashId(h) + if !ok { + panic("tried to convert unknown hash") + } + return v +} + +// writeAndSign writes the data as a payload package and, optionally, signs +// it. hints contains optional information, that is also encrypted, +// that aids the recipients in processing the message. The resulting +// WriteCloser must be closed after the contents of the file have been +// written. If config is nil, sensible defaults will be used. +func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + var signer *packet.PrivateKey + if signed != nil { + signKey, ok := signed.signingKey(config.Now()) + if !ok { + return nil, errors.InvalidArgumentError("no valid signing keys") + } + signer = signKey.PrivateKey + if signer == nil { + return nil, errors.InvalidArgumentError("no private key in signing key") + } + if signer.Encrypted { + return nil, errors.InvalidArgumentError("signing key must be decrypted") + } + } + + var hash crypto.Hash + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h.Available() { + hash = h + break + } + } + + // If the hash specified by config is a candidate, we'll use that. + if configuredHash := config.Hash(); configuredHash.Available() { + for _, hashId := range candidateHashes { + if h, ok := s2k.HashIdToHash(hashId); ok && h == configuredHash { + hash = h + break + } + } + } + + if hash == 0 { + hashId := candidateHashes[0] + name, ok := s2k.HashIdToString(hashId) + if !ok { + name = "#" + strconv.Itoa(int(hashId)) + } + return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)") + } + + if signer != nil { + ops := &packet.OnePassSignature{ + SigType: packet.SigTypeBinary, + Hash: hash, + PubKeyAlgo: signer.PubKeyAlgo, + KeyId: signer.KeyId, + IsLast: true, + } + if err := ops.Serialize(payload); err != nil { + return nil, err + } + } + + if hints == nil { + hints = &FileHints{} + } + + w := payload + if signer != nil { + // If we need to write a signature packet after the literal + // data then we need to stop literalData from closing + // encryptedData. + w = noOpCloser{w} + + } + var epochSeconds uint32 + if !hints.ModTime.IsZero() { + epochSeconds = uint32(hints.ModTime.Unix()) + } + literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds) + if err != nil { + return nil, err + } + + if signer != nil { + return signatureWriter{payload, literalData, hash, hash.New(), signer, config}, nil + } + return literalData, nil +} + +// Encrypt encrypts a message to a number of recipients and, optionally, signs +// it. hints contains optional information, that is also encrypted, that aids +// the recipients in processing the message. The resulting WriteCloser must +// be closed after the contents of the file have been written. +// If config is nil, sensible defaults will be used. +func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) { + if len(to) == 0 { + return nil, errors.InvalidArgumentError("no encryption recipient provided") + } + + // These are the possible ciphers that we'll use for the message. + candidateCiphers := []uint8{ + uint8(packet.CipherAES128), + uint8(packet.CipherAES256), + uint8(packet.CipherCAST5), + } + // These are the possible hash functions that we'll use for the signature. + candidateHashes := []uint8{ + hashToHashId(crypto.SHA256), + hashToHashId(crypto.SHA384), + hashToHashId(crypto.SHA512), + hashToHashId(crypto.SHA1), + hashToHashId(crypto.RIPEMD160), + } + // In the event that a recipient doesn't specify any supported ciphers + // or hash functions, these are the ones that we assume that every + // implementation supports. + defaultCiphers := candidateCiphers[len(candidateCiphers)-1:] + defaultHashes := candidateHashes[len(candidateHashes)-1:] + + encryptKeys := make([]Key, len(to)) + for i := range to { + var ok bool + encryptKeys[i], ok = to[i].encryptionKey(config.Now()) + if !ok { + return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no encryption keys") + } + + sig := to[i].primaryIdentity().SelfSignature + + preferredSymmetric := sig.PreferredSymmetric + if len(preferredSymmetric) == 0 { + preferredSymmetric = defaultCiphers + } + preferredHashes := sig.PreferredHash + if len(preferredHashes) == 0 { + preferredHashes = defaultHashes + } + candidateCiphers = intersectPreferences(candidateCiphers, preferredSymmetric) + candidateHashes = intersectPreferences(candidateHashes, preferredHashes) + } + + if len(candidateCiphers) == 0 || len(candidateHashes) == 0 { + return nil, errors.InvalidArgumentError("cannot encrypt because recipient set shares no common algorithms") + } + + cipher := packet.CipherFunction(candidateCiphers[0]) + // If the cipher specified by config is a candidate, we'll use that. + configuredCipher := config.Cipher() + for _, c := range candidateCiphers { + cipherFunc := packet.CipherFunction(c) + if cipherFunc == configuredCipher { + cipher = cipherFunc + break + } + } + + symKey := make([]byte, cipher.KeySize()) + if _, err := io.ReadFull(config.Random(), symKey); err != nil { + return nil, err + } + + for _, key := range encryptKeys { + if err := packet.SerializeEncryptedKey(ciphertext, key.PublicKey, cipher, symKey, config); err != nil { + return nil, err + } + } + + payload, err := packet.SerializeSymmetricallyEncrypted(ciphertext, cipher, symKey, config) + if err != nil { + return + } + + return writeAndSign(payload, candidateHashes, signed, hints, config) +} + +// Sign signs a message. The resulting WriteCloser must be closed after the +// contents of the file have been written. hints contains optional information +// that aids the recipients in processing the message. +// If config is nil, sensible defaults will be used. +func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) { + if signed == nil { + return nil, errors.InvalidArgumentError("no signer provided") + } + + // These are the possible hash functions that we'll use for the signature. + candidateHashes := []uint8{ + hashToHashId(crypto.SHA256), + hashToHashId(crypto.SHA384), + hashToHashId(crypto.SHA512), + hashToHashId(crypto.SHA1), + hashToHashId(crypto.RIPEMD160), + } + defaultHashes := candidateHashes[len(candidateHashes)-1:] + preferredHashes := signed.primaryIdentity().SelfSignature.PreferredHash + if len(preferredHashes) == 0 { + preferredHashes = defaultHashes + } + candidateHashes = intersectPreferences(candidateHashes, preferredHashes) + return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, config) +} + +// signatureWriter hashes the contents of a message while passing it along to +// literalData. When closed, it closes literalData, writes a signature packet +// to encryptedData and then also closes encryptedData. +type signatureWriter struct { + encryptedData io.WriteCloser + literalData io.WriteCloser + hashType crypto.Hash + h hash.Hash + signer *packet.PrivateKey + config *packet.Config +} + +func (s signatureWriter) Write(data []byte) (int, error) { + s.h.Write(data) + return s.literalData.Write(data) +} + +func (s signatureWriter) Close() error { + sig := &packet.Signature{ + SigType: packet.SigTypeBinary, + PubKeyAlgo: s.signer.PubKeyAlgo, + Hash: s.hashType, + CreationTime: s.config.Now(), + IssuerKeyId: &s.signer.KeyId, + } + + if err := sig.Sign(s.h, s.signer, s.config); err != nil { + return err + } + if err := s.literalData.Close(); err != nil { + return err + } + if err := sig.Serialize(s.encryptedData); err != nil { + return err + } + return s.encryptedData.Close() +} + +// noOpCloser is like an io.NopCloser, but for an io.Writer. +// TODO: we have two of these in OpenPGP packages alone. This probably needs +// to be promoted somewhere more common. +type noOpCloser struct { + w io.Writer +} + +func (c noOpCloser) Write(data []byte) (n int, err error) { + return c.w.Write(data) +} + +func (c noOpCloser) Close() error { + return nil +} diff --git a/vendor/golang.org/x/crypto/ssh/handshake.go b/vendor/golang.org/x/crypto/ssh/handshake.go index c9202b05da..b6bf546b49 100644 --- a/vendor/golang.org/x/crypto/ssh/handshake.go +++ b/vendor/golang.org/x/crypto/ssh/handshake.go @@ -5,7 +5,6 @@ package ssh import ( - "crypto/rand" "errors" "fmt" "io" @@ -501,7 +500,7 @@ func (t *handshakeTransport) sendKexInit() error { CompressionClientServer: supportedCompressions, CompressionServerClient: supportedCompressions, } - io.ReadFull(rand.Reader, msg.Cookie[:]) + io.ReadFull(t.config.Rand, msg.Cookie[:]) // We mutate the KexAlgos slice, in order to add the kex-strict extension algorithm, // and possibly to add the ext-info extension algorithm. Since the slice may be the diff --git a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go index 7376a8dff2..c022e411f0 100644 --- a/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go +++ b/vendor/golang.org/x/crypto/ssh/knownhosts/knownhosts.go @@ -302,8 +302,8 @@ func (k *KnownKey) String() string { // applications can offer an interactive prompt to the user. type KeyError struct { // Want holds the accepted host keys. For each key algorithm, - // there can be one hostkey. If Want is empty, the host is - // unknown. If Want is non-empty, there was a mismatch, which + // there can be multiple hostkeys. If Want is empty, the host + // is unknown. If Want is non-empty, there was a mismatch, which // can signify a MITM attack. Want []KnownKey } @@ -358,34 +358,20 @@ func (db *hostKeyDB) checkAddr(a addr, remoteKey ssh.PublicKey) error { // is just a key for the IP address, but not for the // hostname? - // Algorithm => key. - knownKeys := map[string]KnownKey{} - for _, l := range db.lines { - if l.match(a) { - typ := l.knownKey.Key.Type() - if _, ok := knownKeys[typ]; !ok { - knownKeys[typ] = l.knownKey - } - } - } - keyErr := &KeyError{} - for _, v := range knownKeys { - keyErr.Want = append(keyErr.Want, v) - } - // Unknown remote host. - if len(knownKeys) == 0 { - return keyErr - } + for _, l := range db.lines { + if !l.match(a) { + continue + } - // If the remote host starts using a different, unknown key type, we - // also interpret that as a mismatch. - if known, ok := knownKeys[remoteKey.Type()]; !ok || !keyEq(known.Key, remoteKey) { - return keyErr + keyErr.Want = append(keyErr.Want, l.knownKey) + if keyEq(l.knownKey.Key, remoteKey) { + return nil + } } - return nil + return keyErr } // The Read function parses file contents. diff --git a/vendor/golang.org/x/crypto/ssh/messages.go b/vendor/golang.org/x/crypto/ssh/messages.go index b55f860564..118427bc05 100644 --- a/vendor/golang.org/x/crypto/ssh/messages.go +++ b/vendor/golang.org/x/crypto/ssh/messages.go @@ -818,6 +818,8 @@ func decode(packet []byte) (interface{}, error) { return new(userAuthSuccessMsg), nil case msgUserAuthFailure: msg = new(userAuthFailureMsg) + case msgUserAuthBanner: + msg = new(userAuthBannerMsg) case msgUserAuthPubKeyOk: msg = new(userAuthPubKeyOkMsg) case msgGlobalRequest: diff --git a/vendor/golang.org/x/crypto/ssh/tcpip.go b/vendor/golang.org/x/crypto/ssh/tcpip.go index ef5059a11d..93d844f035 100644 --- a/vendor/golang.org/x/crypto/ssh/tcpip.go +++ b/vendor/golang.org/x/crypto/ssh/tcpip.go @@ -459,7 +459,7 @@ func (c *Client) dial(laddr string, lport int, raddr string, rport int) (Channel return nil, err } go DiscardRequests(in) - return ch, err + return ch, nil } type tcpChan struct { diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go index 81faec7e75..97bd8b06f7 100644 --- a/vendor/golang.org/x/net/http2/frame.go +++ b/vendor/golang.org/x/net/http2/frame.go @@ -225,6 +225,11 @@ var fhBytes = sync.Pool{ }, } +func invalidHTTP1LookingFrameHeader() FrameHeader { + fh, _ := readFrameHeader(make([]byte, frameHeaderLen), strings.NewReader("HTTP/1.1 ")) + return fh +} + // ReadFrameHeader reads 9 bytes from r and returns a FrameHeader. // Most users should use Framer.ReadFrame instead. func ReadFrameHeader(r io.Reader) (FrameHeader, error) { @@ -503,10 +508,16 @@ func (fr *Framer) ReadFrame() (Frame, error) { return nil, err } if fh.Length > fr.maxReadSize { + if fh == invalidHTTP1LookingFrameHeader() { + return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err) + } return nil, ErrFrameTooLarge } payload := fr.getReadBuf(fh.Length) if _, err := io.ReadFull(fr.r, payload); err != nil { + if fh == invalidHTTP1LookingFrameHeader() { + return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err) + } return nil, err } f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, fr.countError, payload) diff --git a/vendor/golang.org/x/net/http2/h2c/h2c.go b/vendor/golang.org/x/net/http2/h2c/h2c.go index 2d6bf861b9..19e94791df 100644 --- a/vendor/golang.org/x/net/http2/h2c/h2c.go +++ b/vendor/golang.org/x/net/http2/h2c/h2c.go @@ -132,11 +132,8 @@ func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // of the body, and reforward the client preface on the net.Conn this function // creates. func initH2CWithPriorKnowledge(w http.ResponseWriter) (net.Conn, error) { - hijacker, ok := w.(http.Hijacker) - if !ok { - return nil, errors.New("h2c: connection does not support Hijack") - } - conn, rw, err := hijacker.Hijack() + rc := http.NewResponseController(w) + conn, rw, err := rc.Hijack() if err != nil { return nil, err } @@ -163,10 +160,6 @@ func h2cUpgrade(w http.ResponseWriter, r *http.Request) (_ net.Conn, settings [] if err != nil { return nil, nil, err } - hijacker, ok := w.(http.Hijacker) - if !ok { - return nil, nil, errors.New("h2c: connection does not support Hijack") - } body, err := io.ReadAll(r.Body) if err != nil { @@ -174,7 +167,8 @@ func h2cUpgrade(w http.ResponseWriter, r *http.Request) (_ net.Conn, settings [] } r.Body = io.NopCloser(bytes.NewBuffer(body)) - conn, rw, err := hijacker.Hijack() + rc := http.NewResponseController(w) + conn, rw, err := rc.Hijack() if err != nil { return nil, nil, err } diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go index b640deb0e0..51fca38f61 100644 --- a/vendor/golang.org/x/net/http2/server.go +++ b/vendor/golang.org/x/net/http2/server.go @@ -1068,7 +1068,10 @@ func (sc *serverConn) serve(conf http2Config) { func (sc *serverConn) handlePingTimer(lastFrameReadTime time.Time) { if sc.pingSent { - sc.vlogf("timeout waiting for PING response") + sc.logf("timeout waiting for PING response") + if f := sc.countErrorFunc; f != nil { + f("conn_close_lost_ping") + } sc.conn.Close() return } diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go index b8322598ae..f8c3c09265 100644 --- a/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -18,7 +18,7 @@ import ( type token struct{} // A Group is a collection of goroutines working on subtasks that are part of -// the same overall task. +// the same overall task. A Group should not be reused for different tasks. // // A zero Group is valid, has no limit on the number of active goroutines, // and does not cancel on error. @@ -46,7 +46,7 @@ func (g *Group) done() { // returns a non-nil error or the first time Wait returns, whichever occurs // first. func WithContext(ctx context.Context) (*Group, context.Context) { - ctx, cancel := withCancelCause(ctx) + ctx, cancel := context.WithCancelCause(ctx) return &Group{cancel: cancel}, ctx } @@ -61,6 +61,7 @@ func (g *Group) Wait() error { } // Go calls the given function in a new goroutine. +// The first call to Go must happen before a Wait. // It blocks until the new goroutine can be added without the number of // active goroutines in the group exceeding the configured limit. // diff --git a/vendor/golang.org/x/sync/errgroup/go120.go b/vendor/golang.org/x/sync/errgroup/go120.go deleted file mode 100644 index f93c740b63..0000000000 --- a/vendor/golang.org/x/sync/errgroup/go120.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.20 - -package errgroup - -import "context" - -func withCancelCause(parent context.Context) (context.Context, func(error)) { - return context.WithCancelCause(parent) -} diff --git a/vendor/golang.org/x/sync/errgroup/pre_go120.go b/vendor/golang.org/x/sync/errgroup/pre_go120.go deleted file mode 100644 index 88ce33434e..0000000000 --- a/vendor/golang.org/x/sync/errgroup/pre_go120.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.20 - -package errgroup - -import "context" - -func withCancelCause(parent context.Context) (context.Context, func(error)) { - ctx, cancel := context.WithCancel(parent) - return ctx, func(error) { cancel() } -} diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go index 9c105f23af..2e73ee1975 100644 --- a/vendor/golang.org/x/sys/cpu/cpu.go +++ b/vendor/golang.org/x/sys/cpu/cpu.go @@ -149,6 +149,18 @@ var ARM struct { _ CacheLinePad } +// The booleans in Loong64 contain the correspondingly named cpu feature bit. +// The struct is padded to avoid false sharing. +var Loong64 struct { + _ CacheLinePad + HasLSX bool // support 128-bit vector extension + HasLASX bool // support 256-bit vector extension + HasCRC32 bool // support CRC instruction + HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction + HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} instruction + _ CacheLinePad +} + // MIPS64X contains the supported CPU features of the current mips64/mips64le // platforms. If the current platform is not mips64/mips64le or the current // operating system is not Linux then all feature flags are false. diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go new file mode 100644 index 0000000000..4f34114329 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_loong64.go @@ -0,0 +1,22 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package cpu + +// HWCAP bits. These are exposed by the Linux kernel. +const ( + hwcap_LOONGARCH_LSX = 1 << 4 + hwcap_LOONGARCH_LASX = 1 << 5 +) + +func doinit() { + // TODO: Features that require kernel support like LSX and LASX can + // be detected here once needed in std library or by the compiler. + Loong64.HasLSX = hwcIsSet(hwCap, hwcap_LOONGARCH_LSX) + Loong64.HasLASX = hwcIsSet(hwCap, hwcap_LOONGARCH_LASX) +} + +func hwcIsSet(hwc uint, val uint) bool { + return hwc&val != 0 +} diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go index 7d902b6847..a428dec9cd 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go +++ b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64 +//go:build linux && !arm && !arm64 && !loong64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64 package cpu diff --git a/vendor/golang.org/x/sys/cpu/cpu_loong64.go b/vendor/golang.org/x/sys/cpu/cpu_loong64.go index 558635850c..45ecb29ae7 100644 --- a/vendor/golang.org/x/sys/cpu/cpu_loong64.go +++ b/vendor/golang.org/x/sys/cpu/cpu_loong64.go @@ -8,5 +8,43 @@ package cpu const cacheLineSize = 64 +// Bit fields for CPUCFG registers, Related reference documents: +// https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_cpucfg +const ( + // CPUCFG1 bits + cpucfg1_CRC32 = 1 << 25 + + // CPUCFG2 bits + cpucfg2_LAM_BH = 1 << 27 + cpucfg2_LAMCAS = 1 << 28 +) + func initOptions() { + options = []option{ + {Name: "lsx", Feature: &Loong64.HasLSX}, + {Name: "lasx", Feature: &Loong64.HasLASX}, + {Name: "crc32", Feature: &Loong64.HasCRC32}, + {Name: "lam_bh", Feature: &Loong64.HasLAM_BH}, + {Name: "lamcas", Feature: &Loong64.HasLAMCAS}, + } + + // The CPUCFG data on Loong64 only reflects the hardware capabilities, + // not the kernel support status, so features such as LSX and LASX that + // require kernel support cannot be obtained from the CPUCFG data. + // + // These features only require hardware capability support and do not + // require kernel specific support, so they can be obtained directly + // through CPUCFG + cfg1 := get_cpucfg(1) + cfg2 := get_cpucfg(2) + + Loong64.HasCRC32 = cfgIsSet(cfg1, cpucfg1_CRC32) + Loong64.HasLAMCAS = cfgIsSet(cfg2, cpucfg2_LAMCAS) + Loong64.HasLAM_BH = cfgIsSet(cfg2, cpucfg2_LAM_BH) +} + +func get_cpucfg(reg uint32) uint32 + +func cfgIsSet(cfg uint32, val uint32) bool { + return cfg&val != 0 } diff --git a/vendor/golang.org/x/sys/cpu/cpu_loong64.s b/vendor/golang.org/x/sys/cpu/cpu_loong64.s new file mode 100644 index 0000000000..71cbaf1ce2 --- /dev/null +++ b/vendor/golang.org/x/sys/cpu/cpu_loong64.s @@ -0,0 +1,13 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// func get_cpucfg(reg uint32) uint32 +TEXT ·get_cpucfg(SB), NOSPLIT|NOFRAME, $0 + MOVW reg+0(FP), R5 + // CPUCFG R5, R4 = 0x00006ca4 + WORD $0x00006ca4 + MOVW R4, ret+8(FP) + RET diff --git a/vendor/golang.org/x/sys/cpu/parse.go b/vendor/golang.org/x/sys/cpu/parse.go index 762b63d688..56a7e1a176 100644 --- a/vendor/golang.org/x/sys/cpu/parse.go +++ b/vendor/golang.org/x/sys/cpu/parse.go @@ -13,7 +13,7 @@ import "strconv" // https://golang.org/cl/209597. func parseRelease(rel string) (major, minor, patch int, ok bool) { // Strip anything after a dash or plus. - for i := 0; i < len(rel); i++ { + for i := range len(rel) { if rel[i] == '-' || rel[i] == '+' { rel = rel[:i] break @@ -21,7 +21,7 @@ func parseRelease(rel string) (major, minor, patch int, ok bool) { } next := func() (int, bool) { - for i := 0; i < len(rel); i++ { + for i := range len(rel) { if rel[i] == '.' { ver, err := strconv.Atoi(rel[:i]) rel = rel[i+1:] diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 099867deed..798f61ad3b 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -602,7 +602,150 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI return } -//sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) +// sys connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) +const minIovec = 8 + +func Readv(fd int, iovs [][]byte) (n int, err error) { + if !darwinKernelVersionMin(11, 0, 0) { + return 0, ENOSYS + } + + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + n, err = readv(fd, iovecs) + readvRacedetect(iovecs, n, err) + return n, err +} + +func Preadv(fd int, iovs [][]byte, offset int64) (n int, err error) { + if !darwinKernelVersionMin(11, 0, 0) { + return 0, ENOSYS + } + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + n, err = preadv(fd, iovecs, offset) + readvRacedetect(iovecs, n, err) + return n, err +} + +func Writev(fd int, iovs [][]byte) (n int, err error) { + if !darwinKernelVersionMin(11, 0, 0) { + return 0, ENOSYS + } + + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = writev(fd, iovecs) + writevRacedetect(iovecs, n) + return n, err +} + +func Pwritev(fd int, iovs [][]byte, offset int64) (n int, err error) { + if !darwinKernelVersionMin(11, 0, 0) { + return 0, ENOSYS + } + + iovecs := make([]Iovec, 0, minIovec) + iovecs = appendBytes(iovecs, iovs) + if raceenabled { + raceReleaseMerge(unsafe.Pointer(&ioSync)) + } + n, err = pwritev(fd, iovecs, offset) + writevRacedetect(iovecs, n) + return n, err +} + +func appendBytes(vecs []Iovec, bs [][]byte) []Iovec { + for _, b := range bs { + var v Iovec + v.SetLen(len(b)) + if len(b) > 0 { + v.Base = &b[0] + } else { + v.Base = (*byte)(unsafe.Pointer(&_zero)) + } + vecs = append(vecs, v) + } + return vecs +} + +func writevRacedetect(iovecs []Iovec, n int) { + if !raceenabled { + return + } + for i := 0; n > 0 && i < len(iovecs); i++ { + m := int(iovecs[i].Len) + if m > n { + m = n + } + n -= m + if m > 0 { + raceReadRange(unsafe.Pointer(iovecs[i].Base), m) + } + } +} + +func readvRacedetect(iovecs []Iovec, n int, err error) { + if !raceenabled { + return + } + for i := 0; n > 0 && i < len(iovecs); i++ { + m := int(iovecs[i].Len) + if m > n { + m = n + } + n -= m + if m > 0 { + raceWriteRange(unsafe.Pointer(iovecs[i].Base), m) + } + } + if err == nil { + raceAcquire(unsafe.Pointer(&ioSync)) + } +} + +func darwinMajorMinPatch() (maj, min, patch int, err error) { + var un Utsname + err = Uname(&un) + if err != nil { + return + } + + var mmp [3]int + c := 0 +Loop: + for _, b := range un.Release[:] { + switch { + case b >= '0' && b <= '9': + mmp[c] = 10*mmp[c] + int(b-'0') + case b == '.': + c++ + if c > 2 { + return 0, 0, 0, ENOTSUP + } + case b == 0: + break Loop + default: + return 0, 0, 0, ENOTSUP + } + } + if c != 2 { + return 0, 0, 0, ENOTSUP + } + return mmp[0], mmp[1], mmp[2], nil +} + +func darwinKernelVersionMin(maj, min, patch int) bool { + actualMaj, actualMin, actualPatch, err := darwinMajorMinPatch() + if err != nil { + return false + } + return actualMaj > maj || actualMaj == maj && (actualMin > min || actualMin == min && actualPatch >= patch) +} + //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) @@ -705,3 +848,7 @@ func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocI //sys write(fd int, p []byte) (n int, err error) //sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) //sys munmap(addr uintptr, length uintptr) (err error) +//sys readv(fd int, iovecs []Iovec) (n int, err error) +//sys preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) +//sys writev(fd int, iovecs []Iovec) (n int, err error) +//sys pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 230a94549a..4958a65708 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -13,6 +13,7 @@ package unix import ( "encoding/binary" + "slices" "strconv" "syscall" "time" @@ -417,7 +418,7 @@ func (sa *SockaddrUnix) sockaddr() (unsafe.Pointer, _Socklen, error) { return nil, 0, EINVAL } sa.raw.Family = AF_UNIX - for i := 0; i < n; i++ { + for i := range n { sa.raw.Path[i] = int8(name[i]) } // length is family (uint16), name, NUL. @@ -507,7 +508,7 @@ func (sa *SockaddrL2) sockaddr() (unsafe.Pointer, _Socklen, error) { psm := (*[2]byte)(unsafe.Pointer(&sa.raw.Psm)) psm[0] = byte(sa.PSM) psm[1] = byte(sa.PSM >> 8) - for i := 0; i < len(sa.Addr); i++ { + for i := range len(sa.Addr) { sa.raw.Bdaddr[i] = sa.Addr[len(sa.Addr)-1-i] } cid := (*[2]byte)(unsafe.Pointer(&sa.raw.Cid)) @@ -589,11 +590,11 @@ func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_CAN sa.raw.Ifindex = int32(sa.Ifindex) rx := (*[4]byte)(unsafe.Pointer(&sa.RxID)) - for i := 0; i < 4; i++ { + for i := range 4 { sa.raw.Addr[i] = rx[i] } tx := (*[4]byte)(unsafe.Pointer(&sa.TxID)) - for i := 0; i < 4; i++ { + for i := range 4 { sa.raw.Addr[i+4] = tx[i] } return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil @@ -618,11 +619,11 @@ func (sa *SockaddrCANJ1939) sockaddr() (unsafe.Pointer, _Socklen, error) { sa.raw.Family = AF_CAN sa.raw.Ifindex = int32(sa.Ifindex) n := (*[8]byte)(unsafe.Pointer(&sa.Name)) - for i := 0; i < 8; i++ { + for i := range 8 { sa.raw.Addr[i] = n[i] } p := (*[4]byte)(unsafe.Pointer(&sa.PGN)) - for i := 0; i < 4; i++ { + for i := range 4 { sa.raw.Addr[i+8] = p[i] } sa.raw.Addr[12] = sa.Addr @@ -911,7 +912,7 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) { // These are EBCDIC encoded by the kernel, but we still need to pad them // with blanks. Initializing with blanks allows the caller to feed in either // a padded or an unpadded string. - for i := 0; i < 8; i++ { + for i := range 8 { sa.raw.Nodeid[i] = ' ' sa.raw.User_id[i] = ' ' sa.raw.Name[i] = ' ' @@ -1148,7 +1149,7 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { var user [8]byte var name [8]byte - for i := 0; i < 8; i++ { + for i := range 8 { user[i] = byte(pp.User_id[i]) name[i] = byte(pp.Name[i]) } @@ -1173,11 +1174,11 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { Ifindex: int(pp.Ifindex), } name := (*[8]byte)(unsafe.Pointer(&sa.Name)) - for i := 0; i < 8; i++ { + for i := range 8 { name[i] = pp.Addr[i] } pgn := (*[4]byte)(unsafe.Pointer(&sa.PGN)) - for i := 0; i < 4; i++ { + for i := range 4 { pgn[i] = pp.Addr[i+8] } addr := (*[1]byte)(unsafe.Pointer(&sa.Addr)) @@ -1188,11 +1189,11 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { Ifindex: int(pp.Ifindex), } rx := (*[4]byte)(unsafe.Pointer(&sa.RxID)) - for i := 0; i < 4; i++ { + for i := range 4 { rx[i] = pp.Addr[i] } tx := (*[4]byte)(unsafe.Pointer(&sa.TxID)) - for i := 0; i < 4; i++ { + for i := range 4 { tx[i] = pp.Addr[i+4] } return sa, nil @@ -2216,10 +2217,7 @@ func readvRacedetect(iovecs []Iovec, n int, err error) { return } for i := 0; n > 0 && i < len(iovecs); i++ { - m := int(iovecs[i].Len) - if m > n { - m = n - } + m := min(int(iovecs[i].Len), n) n -= m if m > 0 { raceWriteRange(unsafe.Pointer(iovecs[i].Base), m) @@ -2270,10 +2268,7 @@ func writevRacedetect(iovecs []Iovec, n int) { return } for i := 0; n > 0 && i < len(iovecs); i++ { - m := int(iovecs[i].Len) - if m > n { - m = n - } + m := min(int(iovecs[i].Len), n) n -= m if m > 0 { raceReadRange(unsafe.Pointer(iovecs[i].Base), m) @@ -2320,12 +2315,7 @@ func isGroupMember(gid int) bool { return false } - for _, g := range groups { - if g == gid { - return true - } - } - return false + return slices.Contains(groups, gid) } func isCapDacOverrideSet() bool { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index 24b346e1a3..813c05b664 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -2512,6 +2512,90 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func readv(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readv readv "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_preadv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_preadv preadv "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func writev(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_writev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pwritev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwritev pwritev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := syscall_syscall(libc_fstat64_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index ebd213100b..fda328582b 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -738,6 +738,26 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readv(SB) +GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) + +TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_preadv(SB) +GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) + +TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_writev(SB) +GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) + +TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwritev(SB) +GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) + TEXT libc_fstat64_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstat64(SB) GLOBL ·libc_fstat64_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 824b9c2d5e..e6f58f3c6f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -2512,6 +2512,90 @@ var libc_munmap_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func readv(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_readv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_readv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_readv readv "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func preadv(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_preadv_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_preadv_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_preadv preadv "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func writev(fd int, iovecs []Iovec) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall(libc_writev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs))) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_writev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_writev writev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pwritev(fd int, iovecs []Iovec, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(iovecs) > 0 { + _p0 = unsafe.Pointer(&iovecs[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := syscall_syscall6(libc_pwritev_trampoline_addr, uintptr(fd), uintptr(_p0), uintptr(len(iovecs)), uintptr(offset), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pwritev_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pwritev pwritev "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Fstat(fd int, stat *Stat_t) (err error) { _, _, e1 := syscall_syscall(libc_fstat_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(stat)), 0) if e1 != 0 { diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 4f178a2293..7f8998b905 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -738,6 +738,26 @@ TEXT libc_munmap_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_munmap_trampoline_addr(SB), RODATA, $8 DATA ·libc_munmap_trampoline_addr(SB)/8, $libc_munmap_trampoline<>(SB) +TEXT libc_readv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_readv(SB) +GLOBL ·libc_readv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_readv_trampoline_addr(SB)/8, $libc_readv_trampoline<>(SB) + +TEXT libc_preadv_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_preadv(SB) +GLOBL ·libc_preadv_trampoline_addr(SB), RODATA, $8 +DATA ·libc_preadv_trampoline_addr(SB)/8, $libc_preadv_trampoline<>(SB) + +TEXT libc_writev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_writev(SB) +GLOBL ·libc_writev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_writev_trampoline_addr(SB)/8, $libc_writev_trampoline<>(SB) + +TEXT libc_pwritev_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pwritev(SB) +GLOBL ·libc_pwritev_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pwritev_trampoline_addr(SB)/8, $libc_pwritev_trampoline<>(SB) + TEXT libc_fstat_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_fstat(SB) GLOBL ·libc_fstat_trampoline_addr(SB), RODATA, $8 diff --git a/vendor/golang.org/x/sys/windows/registry/key.go b/vendor/golang.org/x/sys/windows/registry/key.go index fd8632444e..39aeeb644f 100644 --- a/vendor/golang.org/x/sys/windows/registry/key.go +++ b/vendor/golang.org/x/sys/windows/registry/key.go @@ -164,7 +164,12 @@ loopItems: func CreateKey(k Key, path string, access uint32) (newk Key, openedExisting bool, err error) { var h syscall.Handle var d uint32 - err = regCreateKeyEx(syscall.Handle(k), syscall.StringToUTF16Ptr(path), + var pathPointer *uint16 + pathPointer, err = syscall.UTF16PtrFromString(path) + if err != nil { + return 0, false, err + } + err = regCreateKeyEx(syscall.Handle(k), pathPointer, 0, nil, _REG_OPTION_NON_VOLATILE, access, nil, &h, &d) if err != nil { return 0, false, err @@ -174,7 +179,11 @@ func CreateKey(k Key, path string, access uint32) (newk Key, openedExisting bool // DeleteKey deletes the subkey path of key k and its values. func DeleteKey(k Key, path string) error { - return regDeleteKey(syscall.Handle(k), syscall.StringToUTF16Ptr(path)) + pathPointer, err := syscall.UTF16PtrFromString(path) + if err != nil { + return err + } + return regDeleteKey(syscall.Handle(k), pathPointer) } // A KeyInfo describes the statistics of a key. It is returned by Stat. diff --git a/vendor/golang.org/x/sys/windows/registry/value.go b/vendor/golang.org/x/sys/windows/registry/value.go index 74db26b94d..a1bcbb2362 100644 --- a/vendor/golang.org/x/sys/windows/registry/value.go +++ b/vendor/golang.org/x/sys/windows/registry/value.go @@ -340,7 +340,11 @@ func (k Key) SetBinaryValue(name string, value []byte) error { // DeleteValue removes a named value from the key k. func (k Key) DeleteValue(name string) error { - return regDeleteValue(syscall.Handle(k), syscall.StringToUTF16Ptr(name)) + namePointer, err := syscall.UTF16PtrFromString(name) + if err != nil { + return err + } + return regDeleteValue(syscall.Handle(k), namePointer) } // ReadValueNames returns the value names of key k. diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 9d138de5fe..ad67df2fdb 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -1074,6 +1074,7 @@ const ( IP_ADD_MEMBERSHIP = 0xc IP_DROP_MEMBERSHIP = 0xd IP_PKTINFO = 0x13 + IP_MTU_DISCOVER = 0x47 IPV6_V6ONLY = 0x1b IPV6_UNICAST_HOPS = 0x4 @@ -1083,6 +1084,7 @@ const ( IPV6_JOIN_GROUP = 0xc IPV6_LEAVE_GROUP = 0xd IPV6_PKTINFO = 0x13 + IPV6_MTU_DISCOVER = 0x47 MSG_OOB = 0x1 MSG_PEEK = 0x2 @@ -1132,6 +1134,15 @@ const ( WSASYS_STATUS_LEN = 128 ) +// enum PMTUD_STATE from ws2ipdef.h +const ( + IP_PMTUDISC_NOT_SET = 0 + IP_PMTUDISC_DO = 1 + IP_PMTUDISC_DONT = 2 + IP_PMTUDISC_PROBE = 3 + IP_PMTUDISC_MAX = 4 +) + type WSABuf struct { Len uint32 Buf *byte @@ -1146,6 +1157,22 @@ type WSAMsg struct { Flags uint32 } +type WSACMSGHDR struct { + Len uintptr + Level int32 + Type int32 +} + +type IN_PKTINFO struct { + Addr [4]byte + Ifindex uint32 +} + +type IN6_PKTINFO struct { + Addr [16]byte + Ifindex uint32 +} + // Flags for WSASocket const ( WSA_FLAG_OVERLAPPED = 0x01 diff --git a/vendor/golang.org/x/term/terminal.go b/vendor/golang.org/x/term/terminal.go index f636667fb0..14f89470ab 100644 --- a/vendor/golang.org/x/term/terminal.go +++ b/vendor/golang.org/x/term/terminal.go @@ -44,6 +44,8 @@ type Terminal struct { // bytes, as an index into |line|). If it returns ok=false, the key // press is processed normally. Otherwise it returns a replacement line // and the new cursor position. + // + // This will be disabled during ReadPassword. AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) // Escape contains a pointer to the escape codes for this terminal. @@ -692,6 +694,8 @@ func (t *Terminal) Write(buf []byte) (n int, err error) { // ReadPassword temporarily changes the prompt and reads a password, without // echo, from the terminal. +// +// The AutoCompleteCallback is disabled during this call. func (t *Terminal) ReadPassword(prompt string) (line string, err error) { t.lock.Lock() defer t.lock.Unlock() @@ -699,6 +703,11 @@ func (t *Terminal) ReadPassword(prompt string) (line string, err error) { oldPrompt := t.prompt t.prompt = []rune(prompt) t.echo = false + oldAutoCompleteCallback := t.AutoCompleteCallback + t.AutoCompleteCallback = nil + defer func() { + t.AutoCompleteCallback = oldAutoCompleteCallback + }() line, err = t.readLine() diff --git a/vendor/golang.org/x/text/language/parse.go b/vendor/golang.org/x/text/language/parse.go index 4d57222e77..053336e286 100644 --- a/vendor/golang.org/x/text/language/parse.go +++ b/vendor/golang.org/x/text/language/parse.go @@ -59,7 +59,7 @@ func (c CanonType) Parse(s string) (t Tag, err error) { if changed { tt.RemakeString() } - return makeTag(tt), err + return makeTag(tt), nil } // Compose creates a Tag from individual parts, which may be of type Tag, Base, diff --git a/vendor/modules.txt b/vendor/modules.txt index f4f3972cf3..beb93166e2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -87,6 +87,9 @@ github.com/alecthomas/template/parse # github.com/andybalholm/brotli v1.0.1 ## explicit; go 1.12 github.com/andybalholm/brotli +# github.com/andygrunwald/go-jira v1.15.1 +## explicit; go 1.15 +github.com/andygrunwald/go-jira # github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d ## explicit; go 1.13 github.com/asaskevich/govalidator @@ -216,6 +219,9 @@ github.com/emirpasic/gods/utils # github.com/fatih/color v1.16.0 ## explicit; go 1.17 github.com/fatih/color +# github.com/fatih/structs v1.1.0 +## explicit +github.com/fatih/structs # github.com/felixge/fgprof v0.9.0 ## explicit; go 1.14 github.com/felixge/fgprof @@ -342,12 +348,21 @@ github.com/gofrs/flock # github.com/golang-jwt/jwt v3.2.2+incompatible ## explicit github.com/golang-jwt/jwt +# github.com/golang-jwt/jwt/v4 v4.5.1 +## explicit; go 1.16 +github.com/golang-jwt/jwt/v4 # github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da ## explicit github.com/golang/groupcache/lru # github.com/golang/snappy v0.0.4 ## explicit github.com/golang/snappy +# github.com/google/go-github/v45 v45.0.0 +## explicit; go 1.17 +github.com/google/go-github/v45/github +# github.com/google/go-querystring v1.1.0 +## explicit; go 1.10 +github.com/google/go-querystring/query # github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99 ## explicit; go 1.14 github.com/google/pprof/profile @@ -450,11 +465,6 @@ github.com/lufia/plan9stats github.com/mailru/easyjson/buffer github.com/mailru/easyjson/jlexer github.com/mailru/easyjson/jwriter -# github.com/mark3labs/mcp-go v0.33.0 -## explicit; go 1.23 -github.com/mark3labs/mcp-go/mcp -github.com/mark3labs/mcp-go/server -github.com/mark3labs/mcp-go/util # github.com/maruel/natural v1.1.0 ## explicit; go 1.11 github.com/maruel/natural @@ -568,6 +578,9 @@ github.com/rollbar/rollbar-go # github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 ## explicit; go 1.13 github.com/sergi/go-diff/diffmatchpatch +# github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 +## explicit +github.com/shibukawa/configdir # github.com/shirou/gopsutil/v3 v3.24.5 ## explicit; go 1.18 github.com/shirou/gopsutil/v3/common @@ -588,10 +601,9 @@ github.com/skratchdot/open-golang/open # github.com/sosodev/duration v1.3.1 ## explicit; go 1.17 github.com/sosodev/duration -# github.com/spf13/cast v1.9.2 -## explicit; go 1.21.0 +# github.com/spf13/cast v1.3.0 +## explicit github.com/spf13/cast -github.com/spf13/cast/internal # github.com/spf13/cobra v1.1.1 ## explicit; go 1.12 github.com/spf13/cobra @@ -613,6 +625,10 @@ github.com/tklauser/go-sysconf # github.com/tklauser/numcpus v0.6.1 ## explicit; go 1.13 github.com/tklauser/numcpus +# github.com/trivago/tgo v1.0.7 +## explicit +github.com/trivago/tgo/tcontainer +github.com/trivago/tgo/treflect # github.com/ulikunitz/xz v0.5.11 ## explicit; go 1.12 github.com/ulikunitz/xz @@ -646,9 +662,6 @@ github.com/xanzy/ssh-agent # github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 ## explicit github.com/xi2/xz -# github.com/yosida95/uritemplate/v3 v3.0.2 -## explicit; go 1.14 -github.com/yosida95/uritemplate/v3 # github.com/yusufpapurcu/wmi v1.2.4 ## explicit; go 1.16 github.com/yusufpapurcu/wmi @@ -664,7 +677,7 @@ go.mongodb.org/mongo-driver/bson/bsonrw go.mongodb.org/mongo-driver/bson/bsontype go.mongodb.org/mongo-driver/bson/primitive go.mongodb.org/mongo-driver/x/bsonx/bsoncore -# golang.org/x/crypto v0.35.0 +# golang.org/x/crypto v0.37.0 ## explicit; go 1.23.0 golang.org/x/crypto/acme golang.org/x/crypto/acme/autocert @@ -677,6 +690,12 @@ golang.org/x/crypto/curve25519 golang.org/x/crypto/hkdf golang.org/x/crypto/internal/alias golang.org/x/crypto/internal/poly1305 +golang.org/x/crypto/openpgp +golang.org/x/crypto/openpgp/armor +golang.org/x/crypto/openpgp/elgamal +golang.org/x/crypto/openpgp/errors +golang.org/x/crypto/openpgp/packet +golang.org/x/crypto/openpgp/s2k golang.org/x/crypto/sha3 golang.org/x/crypto/ssh golang.org/x/crypto/ssh/agent @@ -685,7 +704,7 @@ golang.org/x/crypto/ssh/knownhosts # golang.org/x/mod v0.21.0 ## explicit; go 1.22.0 golang.org/x/mod/semver -# golang.org/x/net v0.36.0 +# golang.org/x/net v0.39.0 ## explicit; go 1.23.0 golang.org/x/net/context golang.org/x/net/http/httpguts @@ -696,22 +715,22 @@ golang.org/x/net/idna golang.org/x/net/internal/httpcommon golang.org/x/net/internal/socks golang.org/x/net/proxy -# golang.org/x/sync v0.11.0 -## explicit; go 1.18 +# golang.org/x/sync v0.13.0 +## explicit; go 1.23.0 golang.org/x/sync/errgroup -# golang.org/x/sys v0.30.0 -## explicit; go 1.18 +# golang.org/x/sys v0.32.0 +## explicit; go 1.23.0 golang.org/x/sys/cpu golang.org/x/sys/execabs golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows golang.org/x/sys/windows/registry -# golang.org/x/term v0.29.0 -## explicit; go 1.18 +# golang.org/x/term v0.31.0 +## explicit; go 1.23.0 golang.org/x/term -# golang.org/x/text v0.22.0 -## explicit; go 1.18 +# golang.org/x/text v0.24.0 +## explicit; go 1.23.0 golang.org/x/text/cases golang.org/x/text/internal golang.org/x/text/internal/language