From 5e51eae1dfe83204c05256cfd1c874acc1d47411 Mon Sep 17 00:00:00 2001 From: Zaq? Wiedmann Date: Fri, 28 Dec 2018 01:58:05 -0800 Subject: [PATCH] (ci status) support a short text based pipeline/job status To address #261 & through the use of `--wait` hopefully #240 --- cmd/ci_status.go | 86 +++++++++++++++++++++++++++++++++++++++ go.mod | 6 +-- go.sum | 12 ++++++ internal/gitlab/gitlab.go | 4 +- 4 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 cmd/ci_status.go diff --git a/cmd/ci_status.go b/cmd/ci_status.go new file mode 100644 index 00000000..edb4a9a9 --- /dev/null +++ b/cmd/ci_status.go @@ -0,0 +1,86 @@ +package cmd + +import ( + "fmt" + "log" + "os" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/zaquestion/lab/internal/git" + lab "github.com/zaquestion/lab/internal/gitlab" +) + +// ciStatusCmd represents the run command +var ciStatusCmd = &cobra.Command{ + Use: "status [branch]", + Aliases: []string{"run"}, + Short: "Textual representation of a CI pipeline", + Long: ``, + Example: `lab ci status +lab ci status --wait`, + RunE: nil, + Run: func(cmd *cobra.Command, args []string) { + branch, err := git.CurrentBranch() + if err != nil { + log.Fatal(err) + } + + if len(args) > 1 { + branch = args[1] + } + remote := determineSourceRemote(branch) + if len(args) > 0 { + ok, err := git.IsRemote(args[0]) + if err != nil || !ok { + log.Fatal(args[0], " is not a remote:", err) + } + remote = args[0] + } + rn, err := git.PathWithNameSpace(remote) + if err != nil { + log.Fatal(err) + } + pid := rn + + jobs, err := lab.CIJobs(pid, branch) + if err != nil { + log.Fatal(errors.Wrap(err, "failed to find ci jobs")) + } + jobs = latestJobs(jobs) + + if len(jobs) == 0 { + return + } + + wait, err := cmd.Flags().GetBool("wait") + if err != nil { + log.Fatal(err) + } + + for { + for _, job := range jobs { + fmt.Printf("%s: %s - %s\n", job.Stage, job.Name, job.Status) + } + if !wait { + break + } + if jobs[0].Pipeline.Status != "pending" && + jobs[0].Pipeline.Status != "running" { + break + } + fmt.Println() + } + + fmt.Printf("\nPipeline Status: %s\n", jobs[0].Pipeline.Status) + if wait && jobs[0].Pipeline.Status != "success" { + os.Exit(1) + } + }, +} + +func init() { + ciStatusCmd.MarkZshCompPositionalArgumentCustom(1, "__lab_completion_remote_branches") + ciStatusCmd.Flags().Bool("wait", false, "Continuously print the status and wait to exit until the pipeline finishes. Exit code indicates pipeline status") + ciCmd.AddCommand(ciStatusCmd) +} diff --git a/go.mod b/go.mod index 14fe2054..3bcae0fd 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/derekparker/delve v1.1.0 github.com/gdamore/encoding v0.0.0-20151215212835-b23993cbb635 // indirect github.com/gdamore/tcell v0.0.0-20180416163743-2f258105ca8c - github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 // indirect github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect @@ -33,12 +32,9 @@ require ( github.com/spf13/viper v0.0.0-20180507071007-15738813a09d github.com/stretchr/testify v1.2.2 github.com/tcnksm/go-gitconfig v0.1.2 - github.com/xanzy/go-gitlab v0.11.3 + github.com/xanzy/go-gitlab v0.12.3-0.20181228114601-7bc4155e8bf8 golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045 // indirect golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 - golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc // indirect - golang.org/x/sync v0.0.0-20181108010431-42b317875d0f // indirect - google.golang.org/appengine v1.1.0 // indirect gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 41cb7486..edb07af7 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 h1:zLTLjkaOFEFIOxY5BWLFLwh+cL8vOBW4XJ2aqLE/Tf0= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGEZ+pEmF1OnWuu8AQ9I8iNbHNeno= @@ -86,16 +88,25 @@ github.com/xanzy/go-gitlab v0.0.0-20180921132519-8d21e61ce4a9 h1:gmCeo/bSUp/oLKp github.com/xanzy/go-gitlab v0.0.0-20180921132519-8d21e61ce4a9/go.mod h1:CRKHkvFWNU6C3AEfqLWjnCNnAs4nj8Zk95rX2S3X6Mw= github.com/xanzy/go-gitlab v0.11.3 h1:gSYcSb+pCx3fco6/O3w784/omQVTcrgxRzyf14SBvUQ= github.com/xanzy/go-gitlab v0.11.3/go.mod h1:CRKHkvFWNU6C3AEfqLWjnCNnAs4nj8Zk95rX2S3X6Mw= +github.com/xanzy/go-gitlab v0.12.2 h1:WQY08U/RwrEx1i3x2Fnzsj/oCAzMYMKpk5cq+kHN4Vo= +github.com/xanzy/go-gitlab v0.12.2/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= +github.com/xanzy/go-gitlab v0.12.3-0.20181228114601-7bc4155e8bf8 h1:POfZqSXz6Rr3hKp1tfYDH8L28/1lDLaa6CJnFrrxY/0= +github.com/xanzy/go-gitlab v0.12.3-0.20181228114601-7bc4155e8bf8/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045 h1:Pn8fQdvx+z1avAi7fdM2kRYWQNxGlavNDSyzrQg2SsU= golang.org/x/arch v0.0.0-20181203225421-5a4828bb7045/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= golang.org/x/crypto v0.0.0-20180420171155-e73bf333ef89 h1:YMKUzb2eHV8HdgAr0z9lbGN1Av2h4cgMMsvi+JV60MM= golang.org/x/crypto v0.0.0-20180420171155-e73bf333ef89/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849 h1:FSqE2GGG7wzsYUsWiQ8MZrvEd1EOyU3NCF0AW3Wtltg= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc h1:3ElrZeO6IBP+M8kgu5YFwRo92Gqr+zBg3aooYQ6ziqU= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 h1:JIqe8uIcRBHXDQVvZtHwp80ai3Lw3IJAeJEs55Dc1W0= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -106,6 +117,7 @@ golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/internal/gitlab/gitlab.go b/internal/gitlab/gitlab.go index a7591e42..df7a5864 100644 --- a/internal/gitlab/gitlab.go +++ b/internal/gitlab/gitlab.go @@ -179,7 +179,7 @@ func MRGet(project string, mrNum int) (*gitlab.MergeRequest, error) { return nil, err } - mr, _, err := lab.MergeRequests.GetMergeRequest(p.ID, mrNum) + mr, _, err := lab.MergeRequests.GetMergeRequest(p.ID, mrNum, nil) if err != nil { return nil, err } @@ -224,7 +224,7 @@ func MRList(project string, opts gitlab.ListProjectMergeRequestsOptions, n int) // MRClose closes an mr on a GitLab project func MRClose(pid interface{}, id int) error { - mr, _, err := lab.MergeRequests.GetMergeRequest(pid, id) + mr, _, err := lab.MergeRequests.GetMergeRequest(pid, id, nil) if err != nil { return err }