diff --git a/genqlient.graphql b/genqlient.graphql index 12e2b80..5bf5e9a 100644 --- a/genqlient.graphql +++ b/genqlient.graphql @@ -22,6 +22,31 @@ query GetCloneCredentials { } } +query GetPipeline( + $id: String!, +) { + Pipeline( + id: $id, + ) { + id, + name, + url, + pollInterval, + cloneCredential { + id, + name, + type, + }, + runs { + id, + inProgress, + result, + buildOutput, + stdout, + stderr, + } + } +} mutation CreatePipeline( $name: String!, diff --git a/go.mod b/go.mod index a29c87c..4584f76 100644 --- a/go.mod +++ b/go.mod @@ -3,16 +3,13 @@ module git.ohea.xyz/cursorius/tui go 1.20 require ( + github.com/Khan/genqlient v0.5.0 github.com/charmbracelet/bubbles v0.15.0 github.com/charmbracelet/bubbletea v0.23.2 github.com/charmbracelet/lipgloss v0.6.0 ) require ( - github.com/Khan/genqlient v0.5.0 // indirect - github.com/agnivade/levenshtein v1.1.1 // indirect - github.com/alexflint/go-arg v1.4.2 // indirect - github.com/alexflint/go-scalar v1.0.0 // indirect github.com/atotto/clipboard v0.1.4 // indirect github.com/aymanbagabas/go-osc52 v1.2.1 // indirect github.com/containerd/console v1.0.3 // indirect @@ -27,12 +24,8 @@ require ( github.com/rivo/uniseg v0.2.0 // indirect github.com/sahilm/fuzzy v0.1.0 // indirect github.com/vektah/gqlparser/v2 v2.4.5 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.10 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 5c4ba8d..3c5c5da 100644 --- a/go.sum +++ b/go.sum @@ -4,12 +4,10 @@ github.com/Khan/genqlient v0.5.0 h1:TMZJ+tl/BpbmGyIBiXzKzUftDhw4ZWxQZ+1ydn0gyII= github.com/Khan/genqlient v0.5.0/go.mod h1:EpIvDVXYm01GP6AXzjA7dKriPTH6GmtpmvTAwUUqIX8= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= -github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= -github.com/alexflint/go-arg v1.4.2 h1:lDWZAXxpAnZUq4qwb86p/3rIJJ2Li81EoMbTMujhVa0= github.com/alexflint/go-arg v1.4.2/go.mod h1:9iRbDxne7LcR/GSvEr7ma++GLpdIU1zrghf2y2768kM= -github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70= github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= @@ -31,6 +29,7 @@ github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkX github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -71,6 +70,7 @@ github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= github.com/muesli/termenv v0.14.0 h1:8x9NFfOe8lmIWK4pgy3IfVEy47f+ppe3tUqdPZG2Uy0= github.com/muesli/termenv v0.14.0/go.mod h1:kG/pF1E7fh949Xhe156crRUrHNyK221IuGO7Ez60Uc8= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= @@ -79,6 +79,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -86,6 +87,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/vektah/gqlparser/v2 v2.4.0/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0= @@ -99,7 +101,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -138,12 +139,10 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200815165600-90abf76919f3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -151,6 +150,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/queries/generated.go b/queries/generated.go index 31eb59c..8f2ad79 100644 --- a/queries/generated.go +++ b/queries/generated.go @@ -240,6 +240,112 @@ func (v *GetCloneCredentialsResponse) GetCloneCredentials() []*GetCloneCredentia return v.CloneCredentials } +// GetPipelinePipeline includes the requested fields of the GraphQL type Pipeline. +// The GraphQL type's documentation follows. +// +// A pipeline for running ci jobs +type GetPipelinePipeline struct { + // The id of the pipeline. + Id string `json:"id"` + // The name of the pipeline. + Name string `json:"name"` + // The url of the pipeline. + Url string `json:"url"` + // The polling interval for the pipeline. + PollInterval int `json:"pollInterval"` + // The configured credential for cloning the pipeline source. + CloneCredential *GetPipelinePipelineCloneCredential `json:"cloneCredential"` + // The list of runs for the pipeline. + Runs []GetPipelinePipelineRunsRun `json:"runs"` +} + +// GetId returns GetPipelinePipeline.Id, and is useful for accessing the field via an interface. +func (v *GetPipelinePipeline) GetId() string { return v.Id } + +// GetName returns GetPipelinePipeline.Name, and is useful for accessing the field via an interface. +func (v *GetPipelinePipeline) GetName() string { return v.Name } + +// GetUrl returns GetPipelinePipeline.Url, and is useful for accessing the field via an interface. +func (v *GetPipelinePipeline) GetUrl() string { return v.Url } + +// GetPollInterval returns GetPipelinePipeline.PollInterval, and is useful for accessing the field via an interface. +func (v *GetPipelinePipeline) GetPollInterval() int { return v.PollInterval } + +// GetCloneCredential returns GetPipelinePipeline.CloneCredential, and is useful for accessing the field via an interface. +func (v *GetPipelinePipeline) GetCloneCredential() *GetPipelinePipelineCloneCredential { + return v.CloneCredential +} + +// GetRuns returns GetPipelinePipeline.Runs, and is useful for accessing the field via an interface. +func (v *GetPipelinePipeline) GetRuns() []GetPipelinePipelineRunsRun { return v.Runs } + +// GetPipelinePipelineCloneCredential includes the requested fields of the GraphQL type CloneCredential. +// The GraphQL type's documentation follows. +// +// A credential for authenticating with the pipeline source host. +type GetPipelinePipelineCloneCredential struct { + // The id of the credential. + Id string `json:"id"` + // The name of the credential. + Name string `json:"name"` + // The credential type. + Type string `json:"type"` +} + +// GetId returns GetPipelinePipelineCloneCredential.Id, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineCloneCredential) GetId() string { return v.Id } + +// GetName returns GetPipelinePipelineCloneCredential.Name, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineCloneCredential) GetName() string { return v.Name } + +// GetType returns GetPipelinePipelineCloneCredential.Type, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineCloneCredential) GetType() string { return v.Type } + +// GetPipelinePipelineRunsRun includes the requested fields of the GraphQL type Run. +// The GraphQL type's documentation follows. +// +// A pipeline run +type GetPipelinePipelineRunsRun struct { + // The id of the run. + Id string `json:"id"` + // The progress status of the run. + InProgress *bool `json:"inProgress"` + // The result of the run. + Result *float64 `json:"result"` + // Logs of the top level container build for the run. + BuildOutput *string `json:"buildOutput"` + // The stdout used to validate the run. + Stdout *string `json:"stdout"` + // The stderr used to validate the run. + Stderr *string `json:"stderr"` +} + +// GetId returns GetPipelinePipelineRunsRun.Id, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineRunsRun) GetId() string { return v.Id } + +// GetInProgress returns GetPipelinePipelineRunsRun.InProgress, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineRunsRun) GetInProgress() *bool { return v.InProgress } + +// GetResult returns GetPipelinePipelineRunsRun.Result, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineRunsRun) GetResult() *float64 { return v.Result } + +// GetBuildOutput returns GetPipelinePipelineRunsRun.BuildOutput, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineRunsRun) GetBuildOutput() *string { return v.BuildOutput } + +// GetStdout returns GetPipelinePipelineRunsRun.Stdout, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineRunsRun) GetStdout() *string { return v.Stdout } + +// GetStderr returns GetPipelinePipelineRunsRun.Stderr, and is useful for accessing the field via an interface. +func (v *GetPipelinePipelineRunsRun) GetStderr() *string { return v.Stderr } + +// GetPipelineResponse is returned by GetPipeline on success. +type GetPipelineResponse struct { + Pipeline *GetPipelinePipeline `json:"Pipeline"` +} + +// GetPipeline returns GetPipelineResponse.Pipeline, and is useful for accessing the field via an interface. +func (v *GetPipelineResponse) GetPipeline() *GetPipelinePipeline { return v.Pipeline } + // GetPipelinesPipelinesPipeline includes the requested fields of the GraphQL type Pipeline. // The GraphQL type's documentation follows. // @@ -387,6 +493,14 @@ func (v *__CreateWebhookInput) GetWebhookType() string { return v.WebhookType } // GetPipelineId returns __CreateWebhookInput.PipelineId, and is useful for accessing the field via an interface. func (v *__CreateWebhookInput) GetPipelineId() string { return v.PipelineId } +// __GetPipelineInput is used internally by genqlient +type __GetPipelineInput struct { + Id string `json:"id"` +} + +// GetId returns __GetPipelineInput.Id, and is useful for accessing the field via an interface. +func (v *__GetPipelineInput) GetId() string { return v.Id } + func CreateCloneCredential( ctx context.Context, client graphql.Client, @@ -610,6 +724,54 @@ query GetCloneCredentials { return &data, err } +func GetPipeline( + ctx context.Context, + client graphql.Client, + id string, +) (*GetPipelineResponse, error) { + req := &graphql.Request{ + OpName: "GetPipeline", + Query: ` +query GetPipeline ($id: String!) { + Pipeline(id: $id) { + id + name + url + pollInterval + cloneCredential { + id + name + type + } + runs { + id + inProgress + result + buildOutput + stdout + stderr + } + } +} +`, + Variables: &__GetPipelineInput{ + Id: id, + }, + } + var err error + + var data GetPipelineResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + ctx, + req, + resp, + ) + + return &data, err +} + func GetPipelines( ctx context.Context, client graphql.Client, diff --git a/schema.graphql b/schema.graphql index 493b8a8..3e53e4c 100644 --- a/schema.graphql +++ b/schema.graphql @@ -2,27 +2,63 @@ schema { query: Query mutation: Mutation } -"A credential for authenticating with the pipeline source host." -type CloneCredential { - "The id of the credential." +"A secret available for use inside of a pipeline." +type Secret { + "The id of the secret." id: String! - "The name of the credential." + "The name of the secret." name: String! - "The secret for the credential." + "The secret." secret: String! - "The credential type." - type: String! - "The username to user with the credential." - username: String! } -"A webhook for triggering pipelines" -type Webhook { - "The id of the webhook." +"A runner available for use inside of a pipeline." +type Runner { + "The id of the runner." id: String! - "The secret used to validate the webhook." - secret: String! - "The format of the webhook." - serverType: String! + "The name of the runner." + name: String! + "The token." + token: String! +} +"" +type Query { + "" + CloneCredential( + "The id of the requested credential." + id: String! + ): CloneCredential + "" + CloneCredentials: [CloneCredential]! + "" + Pipeline( + "The id of the requested pipeline." + id: String! + ): Pipeline + "" + Pipelines: [Pipeline]! + "" + Runners: [Runner]! + "" + Secrets: [Secret]! +} +"A pipeline for running ci jobs" +type Pipeline { + "The configured credential for cloning the pipeline source." + cloneCredential: CloneCredential + "The id of the pipeline." + id: String! + "The name of the pipeline." + name: String! + "The polling interval for the pipeline." + pollInterval: Int! + "The list of runs for the pipeline." + runs: [Run!]! + "The list of secrets for the pipeline." + secrets: [Secret!]! + "The url of the pipeline." + url: String! + "The list of webhooks for the pipeline." + webhooks: [Webhook!]! } "" type Mutation { @@ -89,66 +125,32 @@ type Mutation { pipelineId: String! ): Pipeline } -"A runner available for use inside of a pipeline." -type Runner { - "The id of the runner." +"A webhook for triggering pipelines" +type Webhook { + "The id of the webhook." id: String! - "The name of the runner." - name: String! - "The token." - token: String! -} -"A pipeline for running ci jobs" -type Pipeline { - "The configured credential for cloning the pipeline source." - cloneCredential: CloneCredential - "The id of the pipeline." - id: String! - "The name of the pipeline." - name: String! - "The polling interval for the pipeline." - pollInterval: Int! - "The list of runs for the pipeline." - runs: [Run!]! - "The list of secrets for the pipeline." - secrets: [Secret!]! - "The url of the pipeline." - url: String! - "The list of webhooks for the pipeline." - webhooks: [Webhook!]! -} -"A secret available for use inside of a pipeline." -type Secret { - "The id of the secret." - id: String! - "The name of the secret." - name: String! - "The secret." + "The secret used to validate the webhook." secret: String! + "The format of the webhook." + serverType: String! } -"" -type Query { - "" - CloneCredential( - "The id of the requested credential." - id: String! - ): CloneCredential - "" - CloneCredentials: [CloneCredential]! - "" - Pipeline( - "The id of the requested pipeline." - id: String! - ): Pipeline - "" - Pipelines: [Pipeline]! - "" - Runners: [Runner]! - "" - Secrets: [Secret]! +"A credential for authenticating with the pipeline source host." +type CloneCredential { + "The id of the credential." + id: String! + "The name of the credential." + name: String! + "The secret for the credential." + secret: String! + "The credential type." + type: String! + "The username to user with the credential." + username: String! } "A pipeline run" type Run { + "Logs of the top level container build for the run." + buildOutput: String "The id of the run." id: String! "The progress status of the run." diff --git a/tatus b/tatus new file mode 100644 index 0000000..c9a8e4e --- /dev/null +++ b/tatus @@ -0,0 +1,537 @@ +diff --git a/genqlient.graphql b/genqlient.graphql +index 12e2b80..5bf5e9a 100644 +--- a/genqlient.graphql ++++ b/genqlient.graphql +@@ -22,6 +22,31 @@ query GetCloneCredentials { + } + } +  ++query GetPipeline( ++ $id: String!, ++) { ++ Pipeline( ++ id: $id, ++ ) { ++ id, ++ name, ++ url, ++ pollInterval, ++ cloneCredential { ++ id, ++ name, ++ type, ++ }, ++ runs { ++ id, ++ inProgress, ++ result, ++ buildOutput, ++ stdout, ++ stderr, ++ } ++ } ++} +  + mutation CreatePipeline( + $name: String!, +diff --git a/go.mod b/go.mod +index a29c87c..4584f76 100644 +--- a/go.mod ++++ b/go.mod +@@ -3,16 +3,13 @@ module git.ohea.xyz/cursorius/tui + go 1.20 +  + require ( ++ github.com/Khan/genqlient v0.5.0 + github.com/charmbracelet/bubbles v0.15.0 + github.com/charmbracelet/bubbletea v0.23.2 + github.com/charmbracelet/lipgloss v0.6.0 + ) +  + require ( +- github.com/Khan/genqlient v0.5.0 // indirect +- github.com/agnivade/levenshtein v1.1.1 // indirect +- github.com/alexflint/go-arg v1.4.2 // indirect +- github.com/alexflint/go-scalar v1.0.0 // indirect + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aymanbagabas/go-osc52 v1.2.1 // indirect + github.com/containerd/console v1.0.3 // indirect +@@ -27,12 +24,8 @@ require ( + github.com/rivo/uniseg v0.2.0 // indirect + github.com/sahilm/fuzzy v0.1.0 // indirect + github.com/vektah/gqlparser/v2 v2.4.5 // indirect +- golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/text v0.3.7 // indirect +- golang.org/x/tools v0.1.10 // indirect +- golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect +- gopkg.in/yaml.v2 v2.4.0 // indirect + ) +diff --git a/go.sum b/go.sum +index 5c4ba8d..3c5c5da 100644 +--- a/go.sum ++++ b/go.sum +@@ -4,12 +4,10 @@ github.com/Khan/genqlient v0.5.0 h1:TMZJ+tl/BpbmGyIBiXzKzUftDhw4ZWxQZ+1ydn0gyII= + github.com/Khan/genqlient v0.5.0/go.mod h1:EpIvDVXYm01GP6AXzjA7dKriPTH6GmtpmvTAwUUqIX8= + github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= + github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +-github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= + github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +-github.com/alexflint/go-arg v1.4.2 h1:lDWZAXxpAnZUq4qwb86p/3rIJJ2Li81EoMbTMujhVa0= + github.com/alexflint/go-arg v1.4.2/go.mod h1:9iRbDxne7LcR/GSvEr7ma++GLpdIU1zrghf2y2768kM= +-github.com/alexflint/go-scalar v1.0.0 h1:NGupf1XV/Xb04wXskDFzS0KWOLH632W/EO4fAFi+A70= + github.com/alexflint/go-scalar v1.0.0/go.mod h1:GpHzbCOZXEKMEcygYQ5n/aa4Aq84zbxjy3MxYW0gjYw= ++github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= + github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= + github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= + github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +@@ -31,6 +29,7 @@ github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkX + github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= + github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= + github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= ++github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= + github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= + github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= + github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +@@ -71,6 +70,7 @@ github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ + github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= + github.com/muesli/termenv v0.14.0 h1:8x9NFfOe8lmIWK4pgy3IfVEy47f+ppe3tUqdPZG2Uy0= + github.com/muesli/termenv v0.14.0/go.mod h1:kG/pF1E7fh949Xhe156crRUrHNyK221IuGO7Ez60Uc8= ++github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= + github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= + github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= + github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +@@ -79,6 +79,7 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD + github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= + github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= + github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= ++github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= + github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= + github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= + github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +@@ -86,6 +87,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ + github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= + github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= + github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= ++github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= + github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= + github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= + github.com/vektah/gqlparser/v2 v2.4.0/go.mod h1:flJWIR04IMQPGz+BXLrORkrARBxv/rtyIAFvd/MceW0= +@@ -99,7 +101,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= + golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= + golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +-golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= + golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= + golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +@@ -138,12 +139,10 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm + golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= + golang.org/x/tools v0.0.0-20200815165600-90abf76919f3/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= + golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +-golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= + golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= + golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= + golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= + golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= + gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +@@ -151,6 +150,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= + gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= + gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= + gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= + gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= ++gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +diff --git a/queries/generated.go b/queries/generated.go +index 31eb59c..8f2ad79 100644 +--- a/queries/generated.go ++++ b/queries/generated.go +@@ -240,6 +240,112 @@ func (v *GetCloneCredentialsResponse) GetCloneCredentials() []*GetCloneCredentia + return v.CloneCredentials + } +  ++// GetPipelinePipeline includes the requested fields of the GraphQL type Pipeline. ++// The GraphQL type's documentation follows. ++// ++// A pipeline for running ci jobs ++type GetPipelinePipeline struct { ++ // The id of the pipeline. ++ Id string `json:"id"` ++ // The name of the pipeline. ++ Name string `json:"name"` ++ // The url of the pipeline. ++ Url string `json:"url"` ++ // The polling interval for the pipeline. ++ PollInterval int `json:"pollInterval"` ++ // The configured credential for cloning the pipeline source. ++ CloneCredential *GetPipelinePipelineCloneCredential `json:"cloneCredential"` ++ // The list of runs for the pipeline. ++ Runs []GetPipelinePipelineRunsRun `json:"runs"` ++} ++ ++// GetId returns GetPipelinePipeline.Id, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipeline) GetId() string { return v.Id } ++ ++// GetName returns GetPipelinePipeline.Name, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipeline) GetName() string { return v.Name } ++ ++// GetUrl returns GetPipelinePipeline.Url, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipeline) GetUrl() string { return v.Url } ++ ++// GetPollInterval returns GetPipelinePipeline.PollInterval, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipeline) GetPollInterval() int { return v.PollInterval } ++ ++// GetCloneCredential returns GetPipelinePipeline.CloneCredential, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipeline) GetCloneCredential() *GetPipelinePipelineCloneCredential { ++ return v.CloneCredential ++} ++ ++// GetRuns returns GetPipelinePipeline.Runs, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipeline) GetRuns() []GetPipelinePipelineRunsRun { return v.Runs } ++ ++// GetPipelinePipelineCloneCredential includes the requested fields of the GraphQL type CloneCredential. ++// The GraphQL type's documentation follows. ++// ++// A credential for authenticating with the pipeline source host. ++type GetPipelinePipelineCloneCredential struct { ++ // The id of the credential. ++ Id string `json:"id"` ++ // The name of the credential. ++ Name string `json:"name"` ++ // The credential type. ++ Type string `json:"type"` ++} ++ ++// GetId returns GetPipelinePipelineCloneCredential.Id, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineCloneCredential) GetId() string { return v.Id } ++ ++// GetName returns GetPipelinePipelineCloneCredential.Name, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineCloneCredential) GetName() string { return v.Name } ++ ++// GetType returns GetPipelinePipelineCloneCredential.Type, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineCloneCredential) GetType() string { return v.Type } ++ ++// GetPipelinePipelineRunsRun includes the requested fields of the GraphQL type Run. ++// The GraphQL type's documentation follows. ++// ++// A pipeline run ++type GetPipelinePipelineRunsRun struct { ++ // The id of the run. ++ Id string `json:"id"` ++ // The progress status of the run. ++ InProgress *bool `json:"inProgress"` ++ // The result of the run. ++ Result *float64 `json:"result"` ++ // Logs of the top level container build for the run. ++ BuildOutput *string `json:"buildOutput"` ++ // The stdout used to validate the run. ++ Stdout *string `json:"stdout"` ++ // The stderr used to validate the run. ++ Stderr *string `json:"stderr"` ++} ++ ++// GetId returns GetPipelinePipelineRunsRun.Id, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineRunsRun) GetId() string { return v.Id } ++ ++// GetInProgress returns GetPipelinePipelineRunsRun.InProgress, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineRunsRun) GetInProgress() *bool { return v.InProgress } ++ ++// GetResult returns GetPipelinePipelineRunsRun.Result, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineRunsRun) GetResult() *float64 { return v.Result } ++ ++// GetBuildOutput returns GetPipelinePipelineRunsRun.BuildOutput, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineRunsRun) GetBuildOutput() *string { return v.BuildOutput } ++ ++// GetStdout returns GetPipelinePipelineRunsRun.Stdout, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineRunsRun) GetStdout() *string { return v.Stdout } ++ ++// GetStderr returns GetPipelinePipelineRunsRun.Stderr, and is useful for accessing the field via an interface. ++func (v *GetPipelinePipelineRunsRun) GetStderr() *string { return v.Stderr } ++ ++// GetPipelineResponse is returned by GetPipeline on success. ++type GetPipelineResponse struct { ++ Pipeline *GetPipelinePipeline `json:"Pipeline"` ++} ++ ++// GetPipeline returns GetPipelineResponse.Pipeline, and is useful for accessing the field via an interface. ++func (v *GetPipelineResponse) GetPipeline() *GetPipelinePipeline { return v.Pipeline } ++ + // GetPipelinesPipelinesPipeline includes the requested fields of the GraphQL type Pipeline. + // The GraphQL type's documentation follows. + // +@@ -387,6 +493,14 @@ func (v *__CreateWebhookInput) GetWebhookType() string { return v.WebhookType } + // GetPipelineId returns __CreateWebhookInput.PipelineId, and is useful for accessing the field via an interface. + func (v *__CreateWebhookInput) GetPipelineId() string { return v.PipelineId } +  ++// __GetPipelineInput is used internally by genqlient ++type __GetPipelineInput struct { ++ Id string `json:"id"` ++} ++ ++// GetId returns __GetPipelineInput.Id, and is useful for accessing the field via an interface. ++func (v *__GetPipelineInput) GetId() string { return v.Id } ++ + func CreateCloneCredential( + ctx context.Context, + client graphql.Client, +@@ -610,6 +724,54 @@ query GetCloneCredentials { + return &data, err + } +  ++func GetPipeline( ++ ctx context.Context, ++ client graphql.Client, ++ id string, ++) (*GetPipelineResponse, error) { ++ req := &graphql.Request{ ++ OpName: "GetPipeline", ++ Query: ` ++query GetPipeline ($id: String!) { ++ Pipeline(id: $id) { ++ id ++ name ++ url ++ pollInterval ++ cloneCredential { ++ id ++ name ++ type ++ } ++ runs { ++ id ++ inProgress ++ result ++ buildOutput ++ stdout ++ stderr ++ } ++ } ++} ++`, ++ Variables: &__GetPipelineInput{ ++ Id: id, ++ }, ++ } ++ var err error ++ ++ var data GetPipelineResponse ++ resp := &graphql.Response{Data: &data} ++ ++ err = client.MakeRequest( ++ ctx, ++ req, ++ resp, ++ ) ++ ++ return &data, err ++} ++ + func GetPipelines( + ctx context.Context, + client graphql.Client, +diff --git a/schema.graphql b/schema.graphql +index 493b8a8..3e53e4c 100644 +--- a/schema.graphql ++++ b/schema.graphql +@@ -2,27 +2,63 @@ schema { + query: Query + mutation: Mutation + } +-"A credential for authenticating with the pipeline source host." +-type CloneCredential { +- "The id of the credential." ++"A secret available for use inside of a pipeline." ++type Secret { ++ "The id of the secret." + id: String! +- "The name of the credential." ++ "The name of the secret." + name: String! +- "The secret for the credential." ++ "The secret." + secret: String! +- "The credential type." +- type: String! +- "The username to user with the credential." +- username: String! + } +-"A webhook for triggering pipelines" +-type Webhook { +- "The id of the webhook." ++"A runner available for use inside of a pipeline." ++type Runner { ++ "The id of the runner." + id: String! +- "The secret used to validate the webhook." +- secret: String! +- "The format of the webhook." +- serverType: String! ++ "The name of the runner." ++ name: String! ++ "The token." ++ token: String! ++} ++"" ++type Query { ++ "" ++ CloneCredential( ++ "The id of the requested credential." ++ id: String! ++ ): CloneCredential ++ "" ++ CloneCredentials: [CloneCredential]! ++ "" ++ Pipeline( ++ "The id of the requested pipeline." ++ id: String! ++ ): Pipeline ++ "" ++ Pipelines: [Pipeline]! ++ "" ++ Runners: [Runner]! ++ "" ++ Secrets: [Secret]! ++} ++"A pipeline for running ci jobs" ++type Pipeline { ++ "The configured credential for cloning the pipeline source." ++ cloneCredential: CloneCredential ++ "The id of the pipeline." ++ id: String! ++ "The name of the pipeline." ++ name: String! ++ "The polling interval for the pipeline." ++ pollInterval: Int! ++ "The list of runs for the pipeline." ++ runs: [Run!]! ++ "The list of secrets for the pipeline." ++ secrets: [Secret!]! ++ "The url of the pipeline." ++ url: String! ++ "The list of webhooks for the pipeline." ++ webhooks: [Webhook!]! + } + "" + type Mutation { +@@ -89,66 +125,32 @@ type Mutation { + pipelineId: String! + ): Pipeline + } +-"A runner available for use inside of a pipeline." +-type Runner { +- "The id of the runner." +- id: String! +- "The name of the runner." +- name: String! +- "The token." +- token: String! +-} +-"A pipeline for running ci jobs" +-type Pipeline { +- "The configured credential for cloning the pipeline source." +- cloneCredential: CloneCredential +- "The id of the pipeline." ++"A webhook for triggering pipelines" ++type Webhook { ++ "The id of the webhook." + id: String! +- "The name of the pipeline." +- name: String! +- "The polling interval for the pipeline." +- pollInterval: Int! +- "The list of runs for the pipeline." +- runs: [Run!]! +- "The list of secrets for the pipeline." +- secrets: [Secret!]! +- "The url of the pipeline." +- url: String! +- "The list of webhooks for the pipeline." +- webhooks: [Webhook!]! ++ "The secret used to validate the webhook." ++ secret: String! ++ "The format of the webhook." ++ serverType: String! + } +-"A secret available for use inside of a pipeline." +-type Secret { +- "The id of the secret." ++"A credential for authenticating with the pipeline source host." ++type CloneCredential { ++ "The id of the credential." + id: String! +- "The name of the secret." ++ "The name of the credential." + name: String! +- "The secret." ++ "The secret for the credential." + secret: String! +-} +-"" +-type Query { +- "" +- CloneCredential( +- "The id of the requested credential." +- id: String! +- ): CloneCredential +- "" +- CloneCredentials: [CloneCredential]! +- "" +- Pipeline( +- "The id of the requested pipeline." +- id: String! +- ): Pipeline +- "" +- Pipelines: [Pipeline]! +- "" +- Runners: [Runner]! +- "" +- Secrets: [Secret]! ++ "The credential type." ++ type: String! ++ "The username to user with the credential." ++ username: String! + } + "A pipeline run" + type Run { ++ "Logs of the top level container build for the run." ++ buildOutput: String + "The id of the run." + id: String! + "The progress status of the run." +diff --git a/widget/pipelineList.go b/widget/pipelineList.go +index f38a92f..cd7aabf 100644 +--- a/widget/pipelineList.go ++++ b/widget/pipelineList.go +@@ -42,16 +42,16 @@ func (m pipelineWidgetList) Update(msg tea.Msg) (tea.Model, tea.Cmd) { +  + case "enter": + if m.list.Index() < len(m.list.Items())-1 { +- //item := m.list.SelectedItem() +- //if item, ok := item.(pipelineListItem); ok { +- // return m, func() tea.Cmd { +- // view, err := createPipelineEditForm(client, item.id) +- // if err != nil { +- // return err +- // } +- // return pipelineWidgetScreenSwitch(view) +- // } +- //} ++ item := m.list.SelectedItem() ++ if item, ok := item.(pipelineListItem); ok { ++ return m, func() tea.Msg { ++ view, err := createPipelineWidgetView(m.client, item.id) ++ if err != nil { ++ return err ++ } ++ return pipelineWidgetScreenSwitch(view) ++ } ++ } + } else { + return m, func() tea.Msg { + view, err := createPipelineCreateForm(m.client, m.list.Width(), m.list.Height()) diff --git a/widget/pipelineList.go b/widget/pipelineList.go index f38a92f..cd7aabf 100644 --- a/widget/pipelineList.go +++ b/widget/pipelineList.go @@ -42,16 +42,16 @@ func (m pipelineWidgetList) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "enter": if m.list.Index() < len(m.list.Items())-1 { - //item := m.list.SelectedItem() - //if item, ok := item.(pipelineListItem); ok { - // return m, func() tea.Cmd { - // view, err := createPipelineEditForm(client, item.id) - // if err != nil { - // return err - // } - // return pipelineWidgetScreenSwitch(view) - // } - //} + item := m.list.SelectedItem() + if item, ok := item.(pipelineListItem); ok { + return m, func() tea.Msg { + view, err := createPipelineWidgetView(m.client, item.id) + if err != nil { + return err + } + return pipelineWidgetScreenSwitch(view) + } + } } else { return m, func() tea.Msg { view, err := createPipelineCreateForm(m.client, m.list.Width(), m.list.Height()) diff --git a/widget/pipelineView.go b/widget/pipelineView.go new file mode 100644 index 0000000..e981c5f --- /dev/null +++ b/widget/pipelineView.go @@ -0,0 +1,263 @@ +package widget + +import ( + "context" + "fmt" + "io" + + "git.ohea.xyz/cursorius/tui/queries" + + "github.com/Khan/genqlient/graphql" + "github.com/charmbracelet/bubbles/list" + "github.com/charmbracelet/bubbles/viewport" + tea "github.com/charmbracelet/bubbletea" +) + +type pipelineWidgetViewPage int + +const ( + topLevel pipelineWidgetViewPage = 0 + viewRun = 1 + viewRunBuildOutput = 2 + viewRunStdout = 3 + viewRunStderr = 4 +) + +type pipelineWidgetView struct { + client graphql.Client + page pipelineWidgetViewPage + pipeline queries.GetPipelinePipeline + runsList list.Model + viewRunSelector list.Model + viewRunBuildOutputPager viewport.Model + viewRunStdoutPager viewport.Model + viewRunStderrPager viewport.Model +} + +func (m pipelineWidgetView) Init() tea.Cmd { + return nil +} + +func (m pipelineWidgetView) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.WindowSizeMsg: + m.runsList.SetWidth(msg.Width - 20) + m.runsList.SetHeight(msg.Height - 20) + case tea.KeyMsg: + switch msg.String() { + case "r": + return m, func() tea.Msg { + view, err := createPipelineWidgetView(m.client, m.pipeline.Id) + if err != nil { + return err + } + return pipelineWidgetScreenSwitch(view) + } + case "backspace": + switch m.page { + case topLevel: + return m, func() tea.Msg { + view, err := createPipelineWidgetList(m.client) + if err != nil { + return err + } + return pipelineWidgetScreenSwitch(view) + } + case viewRun: + m.page = topLevel + case viewRunBuildOutput: + m.page = viewRun + case viewRunStderr: + m.page = viewRun + case viewRunStdout: + m.page = viewRun + } + case "enter": + switch m.page { + case topLevel: + run := m.pipeline.Runs[m.runsList.Index()] + + content := []list.Item{ + pipelineWidgetViewRunsSelectorItem(fmt.Sprintf("ID: %v", run.Id)), + } + + if run.InProgress != nil { + content = append(content, pipelineWidgetViewRunsSelectorItem(fmt.Sprintf("In Progress: %v", *run.InProgress))) + } else { + content = append(content, pipelineWidgetViewRunsSelectorItem("In Progress: null")) + } + if run.Result != nil { + content = append(content, pipelineWidgetViewRunsSelectorItem(fmt.Sprintf("Result: %v", *run.Result))) + } else { + content = append(content, pipelineWidgetViewRunsSelectorItem("Result: null")) + } + content = append(content, pipelineWidgetViewRunsSelectorItem("View Build Output")) + content = append(content, pipelineWidgetViewRunsSelectorItem("View Stdout")) + content = append(content, pipelineWidgetViewRunsSelectorItem("View Stderr")) + + runOutputList := list.New(content, pipelineWigetViewRunsSelectorItemDelegate{}, m.runsList.Width(), m.runsList.Height()) + runOutputList.SetShowStatusBar(false) + runOutputList.Title = "View Run" + runOutputList.DisableQuitKeybindings() + + m.viewRunSelector = runOutputList + + m.page = viewRun + case viewRun: + run := m.pipeline.Runs[m.runsList.Index()] + switch m.viewRunSelector.Index() { + case 3: + if run.BuildOutput == nil { + break + } + m.viewRunBuildOutputPager = viewport.New(m.runsList.Width(), m.runsList.Height()) + m.viewRunBuildOutputPager.SetContent(*run.BuildOutput) + m.page = viewRunBuildOutput + case 4: + if run.Stdout == nil { + break + } + m.viewRunStdoutPager = viewport.New(m.runsList.Width(), m.runsList.Height()) + m.viewRunStdoutPager.SetContent(*run.Stdout) + + m.page = viewRunStdout + case 5: + if run.Stderr == nil { + break + } + m.viewRunStderrPager = viewport.New(m.runsList.Width(), m.runsList.Height()) + m.viewRunStderrPager.SetContent(*run.Stderr) + + m.page = viewRunStderr + } + } + + } + } + + var cmd tea.Cmd + switch m.page { + case topLevel: + m.runsList, cmd = m.runsList.Update(msg) + case viewRun: + m.viewRunSelector, cmd = m.viewRunSelector.Update(msg) + case viewRunBuildOutput: + m.viewRunBuildOutputPager, cmd = m.viewRunBuildOutputPager.Update(msg) + case viewRunStdout: + m.viewRunStdoutPager, cmd = m.viewRunStdoutPager.Update(msg) + case viewRunStderr: + m.viewRunStderrPager, cmd = m.viewRunStderrPager.Update(msg) + } + + return m, cmd +} + +func (m pipelineWidgetView) View() string { + s := "" + switch m.page { + case topLevel: + s += fmt.Sprintf("Pipeline: %v\n\n", m.pipeline.Name) + s += fmt.Sprintf("Id: %v\n", m.pipeline.Id) + s += fmt.Sprintf("Url: %v\n", m.pipeline.Url) + s += fmt.Sprintf("Poll Interval: %v\n", m.pipeline.PollInterval) + if m.pipeline.CloneCredential != nil { + s += fmt.Sprintf("Clone Credential: %v (%v)\n\n", m.pipeline.CloneCredential.Name, m.pipeline.CloneCredential.Type) + } else { + s += fmt.Sprintf("Clone Credential: None\n\n") + } + s += m.runsList.View() + case viewRun: + s += m.viewRunSelector.View() + case viewRunBuildOutput: + s += m.viewRunBuildOutputPager.View() + case viewRunStdout: + s += m.viewRunStdoutPager.View() + case viewRunStderr: + s += m.viewRunStderrPager.View() + + } + return s +} + +func createPipelineWidgetView(client graphql.Client, id string) (tea.Model, error) { + + getPipelineResp, err := queries.GetPipeline(context.Background(), client, id) + if err != nil { + return nil, err + } + + if getPipelineResp.Pipeline == nil { + return nil, fmt.Errorf("Server did not give us a pipeline") + } + + var content []list.Item + + for _, run := range getPipelineResp.Pipeline.Runs { + content = append(content, pipelineWidgetViewRunsItem{ + id: run.Id, + }) + } + + runsList := list.New(content, pipelineWigetViewRunsItemDelegate{}, 0, 0) + runsList.SetShowStatusBar(false) + runsList.Title = "Runs" + + return pipelineWidgetView{ + client: client, + page: topLevel, + pipeline: *getPipelineResp.Pipeline, + runsList: runsList, + }, nil +} + +type pipelineWidgetViewRunsItem struct { + id string +} + +func (i pipelineWidgetViewRunsItem) FilterValue() string { return "" } + +type pipelineWigetViewRunsItemDelegate struct{} + +func (d pipelineWigetViewRunsItemDelegate) Height() int { return 1 } +func (d pipelineWigetViewRunsItemDelegate) Spacing() int { return 0 } +func (d pipelineWigetViewRunsItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil } +func (d pipelineWigetViewRunsItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { + switch i := listItem.(type) { + case pipelineWidgetViewRunsItem: + fn := itemStyle.Render + if index == m.Index() { + fn = func(s string) string { + return selectedItemStyle.Render("> " + s) + } + } + + str := fn(i.id) + fmt.Fprint(w, str) + } +} + +type pipelineWidgetViewRunsSelectorItem string + +func (i pipelineWidgetViewRunsSelectorItem) FilterValue() string { return "" } + +type pipelineWigetViewRunsSelectorItemDelegate struct{} + +func (d pipelineWigetViewRunsSelectorItemDelegate) Height() int { return 1 } +func (d pipelineWigetViewRunsSelectorItemDelegate) Spacing() int { return 0 } +func (d pipelineWigetViewRunsSelectorItemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { + return nil +} +func (d pipelineWigetViewRunsSelectorItemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { + switch i := listItem.(type) { + case pipelineWidgetViewRunsSelectorItem: + fn := itemStyle.Render + if index == m.Index() { + fn = func(s string) string { + return selectedItemStyle.Render("> " + s) + } + } + + str := fn(string(i)) + fmt.Fprint(w, str) + } +}