From 59d4637b28aeea50bc44be7d912794b8400334c7 Mon Sep 17 00:00:00 2001 From: Sebastian Gumprich Date: Tue, 21 Feb 2023 15:04:27 +0000 Subject: [PATCH] feat(schedule): Add command to run schedules --- api/schedule.go | 19 +++++- commands/schedule/run/run.go | 64 ++++++++++++++++++ commands/schedule/run/run_test.go | 108 ++++++++++++++++++++++++++++++ commands/schedule/schedule.go | 2 + docs/source/schedule/index.md | 1 + docs/source/schedule/run.md | 32 +++++++++ 6 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 commands/schedule/run/run.go create mode 100644 commands/schedule/run/run_test.go create mode 100644 docs/source/schedule/run.md diff --git a/api/schedule.go b/api/schedule.go index 9275c882..a03b364a 100644 --- a/api/schedule.go +++ b/api/schedule.go @@ -1,6 +1,10 @@ package api -import "github.com/xanzy/go-gitlab" +import ( + "fmt" + + "github.com/xanzy/go-gitlab" +) var GetSchedules = func(client *gitlab.Client, l *gitlab.ListPipelineSchedulesOptions, repo string) ([]*gitlab.PipelineSchedule, error) { if client == nil { @@ -16,3 +20,16 @@ var GetSchedules = func(client *gitlab.Client, l *gitlab.ListPipelineSchedulesOp } return schedules, nil } + +var RunSchedule = func(client *gitlab.Client, repo string, schedule int, opts ...gitlab.RequestOptionFunc) error { + if client == nil { + client = apiClient.Lab() + } + + _, err := client.PipelineSchedules.RunPipelineSchedule(repo, schedule, opts...) + if err != nil { + return fmt.Errorf("running scheduled pipeline status: %w", err) + } + + return nil +} diff --git a/commands/schedule/run/run.go b/commands/schedule/run/run.go new file mode 100644 index 00000000..d4118c88 --- /dev/null +++ b/commands/schedule/run/run.go @@ -0,0 +1,64 @@ +package run + +import ( + "fmt" + "strconv" + + "gitlab.com/gitlab-org/cli/api" + "gitlab.com/gitlab-org/cli/commands/cmdutils" + "gitlab.com/gitlab-org/cli/pkg/iostreams" + + "github.com/MakeNowJust/heredoc" + "github.com/spf13/cobra" +) + +type RunOpts struct { + ScheduleId int + IO *iostreams.IOStreams +} + +func NewCmdRun(f *cmdutils.Factory) *cobra.Command { + opts := &RunOpts{ + IO: f.IO, + } + scheduleRunCmd := &cobra.Command{ + Use: "run ", + Short: `Run the specified scheduled pipeline.`, + Example: heredoc.Doc(` + glab schedule run 1 + `), + Long: ``, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + apiClient, err := f.HttpClient() + if err != nil { + return err + } + + repo, err := f.BaseRepo() + if err != nil { + return err + } + + id, err := strconv.ParseUint(args[0], 10, 64) + if err != nil { + return err + } + + opts.ScheduleId = int(id) + if err != nil { + return err + } + + err = api.RunSchedule(apiClient, repo.FullName(), opts.ScheduleId) + if err != nil { + return err + } + + fmt.Fprintln(opts.IO.StdOut, "Started schedule with ID", opts.ScheduleId) + + return nil + }, + } + return scheduleRunCmd +} diff --git a/commands/schedule/run/run_test.go b/commands/schedule/run/run_test.go new file mode 100644 index 00000000..45c8b0a9 --- /dev/null +++ b/commands/schedule/run/run_test.go @@ -0,0 +1,108 @@ +package run + +import ( + "bytes" + "io" + "os" + "testing" + + "github.com/acarl005/stripansi" + "github.com/google/shlex" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/xanzy/go-gitlab" + "gitlab.com/gitlab-org/cli/api" + "gitlab.com/gitlab-org/cli/commands/cmdtest" + "gitlab.com/gitlab-org/cli/commands/cmdutils" + "gitlab.com/gitlab-org/cli/internal/config" + "gitlab.com/gitlab-org/cli/pkg/iostreams" +) + +func Test_ScheduleRun(t *testing.T) { + defer config.StubConfig(`--- +hosts: + gitlab.com: + username: monalisa + token: OTOKEN +`, "")() + + io, _, Stderr, stderr := iostreams.Test() + stubFactory, _ := cmdtest.StubFactoryWithConfig("") + stubFactory.IO = io + stubFactory.IO.IsaTTY = true + stubFactory.IO.IsErrTTY = true + + api.RunSchedule = func(client *gitlab.Client, repo string, schedule int, opts ...gitlab.RequestOptionFunc) error { + _, err := stubFactory.BaseRepo() + if err != nil { + return err + } + return nil + } + + testCases := []struct { + Name string + ExpectedMsg []string + wantErr bool + cli string + wantStderr string + }{ + { + Name: "Schedule 1 started", + ExpectedMsg: []string{"Started schedule with ID 1"}, + cli: "1", + }, + } + + cmd := NewCmdRun(stubFactory) + cmdutils.EnableRepoOverride(cmd, stubFactory) + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + argv, err := shlex.Split(tc.cli) + require.NoError(t, err) + cmd.SetArgs(argv) + + _, err = cmd.ExecuteC() + if err != nil { + if tc.wantErr == true { + if assert.Error(t, err) { + assert.Equal(t, tc.wantStderr, err.Error()) + } + return + } + } + + out := stripansi.Strip(Stderr.String()) + + for _, msg := range tc.ExpectedMsg { + assert.Contains(t, out, msg) + assert.Equal(t, "", stderr.String()) + } + }) + } +} + +func Test_ScheduleRunNoID(t *testing.T) { + old := os.Stderr // keep backup of the real Stderr + r, w, _ := os.Pipe() + os.Stderr = w + + assert.Error(t, NewCmdRun(&cmdutils.Factory{}).Execute()) + + outC := make(chan string) + // copy the output in a separate goroutine so printing can't block indefinitely + go func() { + var buf bytes.Buffer + _, err := io.Copy(&buf, r) + require.NoError(t, err) + outC <- buf.String() + }() + + // back to normal state + w.Close() + os.Stderr = old // restoring the real Stderr + out := <-outC + + assert.Contains(t, out, "Error: accepts 1 arg(s), received 0\nUsage:\n run [flags]\n\nExamples:\nglab schedule run 1\n\n\nFlags:\n -h, --help help for run\n\n") +} diff --git a/commands/schedule/schedule.go b/commands/schedule/schedule.go index 33963b18..091ee625 100644 --- a/commands/schedule/schedule.go +++ b/commands/schedule/schedule.go @@ -2,6 +2,7 @@ package schedule import ( scheduleListCmd "gitlab.com/gitlab-org/cli/commands/schedule/list" + scheduleRunCmd "gitlab.com/gitlab-org/cli/commands/schedule/run" "gitlab.com/gitlab-org/cli/commands/cmdutils" @@ -19,6 +20,7 @@ func NewCmdSchedule(f *cmdutils.Factory) *cobra.Command { cmdutils.EnableRepoOverride(scheduleCmd, f) scheduleCmd.AddCommand(scheduleListCmd.NewCmdList(f)) + scheduleCmd.AddCommand(scheduleRunCmd.NewCmdRun(f)) return scheduleCmd } diff --git a/docs/source/schedule/index.md b/docs/source/schedule/index.md index c9368a9d..77baafe1 100755 --- a/docs/source/schedule/index.md +++ b/docs/source/schedule/index.md @@ -28,3 +28,4 @@ Work with GitLab CI schedules ## Subcommands - [list](list.md) +- [run](run.md) diff --git a/docs/source/schedule/run.md b/docs/source/schedule/run.md new file mode 100644 index 00000000..c6a6b3c2 --- /dev/null +++ b/docs/source/schedule/run.md @@ -0,0 +1,32 @@ +--- +stage: Create +group: Code Review +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments +--- + + + +# `glab schedule run` + +Run the specified scheduled pipeline. + +```plaintext +glab schedule run [flags] +``` + +## Examples + +```plaintext +glab schedule run 1 + +``` + +## Options inherited from parent commands + +```plaintext + --help Show help for command + -R, --repo OWNER/REPO Select another repository using the OWNER/REPO or `GROUP/NAMESPACE/REPO` format or full URL or git URL +```