mirror of https://gitlab.com/gitlab-org/cli.git
Merge branch 'pipeline-trigger-support' into 'main'
feat: Add new command to run Pipeline Triggers See merge request https://gitlab.com/gitlab-org/cli/-/merge_requests/1414 Merged-by: Jay McCure <jmccure@gitlab.com> Approved-by: Timo Furrer <tfurrer@gitlab.com> Approved-by: Jay McCure <jmccure@gitlab.com> Reviewed-by: Clément Saccoccio <git-clement@saccoccio.me> Reviewed-by: Jay McCure <jmccure@gitlab.com> Reviewed-by: Timo Furrer <tfurrer@gitlab.com> Co-authored-by: Clément Saccoccio <git-clement@saccoccio.me>
This commit is contained in:
commit
44dc7b7250
|
@ -438,6 +438,14 @@ var CreatePipeline = func(client *gitlab.Client, projectID interface{}, opts *gi
|
||||||
return pipe, err
|
return pipe, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var RunPipelineTrigger = func(client *gitlab.Client, projectID interface{}, opts *gitlab.RunPipelineTriggerOptions) (*gitlab.Pipeline, error) {
|
||||||
|
if client == nil {
|
||||||
|
client = apiClient.Lab()
|
||||||
|
}
|
||||||
|
pipe, _, err := client.PipelineTriggers.RunPipelineTrigger(projectID, opts)
|
||||||
|
return pipe, err
|
||||||
|
}
|
||||||
|
|
||||||
var DownloadArtifactJob = func(client *gitlab.Client, repo string, ref string, opts *gitlab.DownloadArtifactsFileOptions) (*bytes.Reader, error) {
|
var DownloadArtifactJob = func(client *gitlab.Client, repo string, ref string, opts *gitlab.DownloadArtifactsFileOptions) (*bytes.Reader, error) {
|
||||||
if client == nil {
|
if client == nil {
|
||||||
client = apiClient.Lab()
|
client = apiClient.Lab()
|
||||||
|
|
|
@ -10,9 +10,10 @@ import (
|
||||||
pipeListCmd "gitlab.com/gitlab-org/cli/commands/ci/list"
|
pipeListCmd "gitlab.com/gitlab-org/cli/commands/ci/list"
|
||||||
pipeRetryCmd "gitlab.com/gitlab-org/cli/commands/ci/retry"
|
pipeRetryCmd "gitlab.com/gitlab-org/cli/commands/ci/retry"
|
||||||
pipeRunCmd "gitlab.com/gitlab-org/cli/commands/ci/run"
|
pipeRunCmd "gitlab.com/gitlab-org/cli/commands/ci/run"
|
||||||
|
pipeRunTrigCmd "gitlab.com/gitlab-org/cli/commands/ci/run_trig"
|
||||||
pipeStatusCmd "gitlab.com/gitlab-org/cli/commands/ci/status"
|
pipeStatusCmd "gitlab.com/gitlab-org/cli/commands/ci/status"
|
||||||
ciTraceCmd "gitlab.com/gitlab-org/cli/commands/ci/trace"
|
ciTraceCmd "gitlab.com/gitlab-org/cli/commands/ci/trace"
|
||||||
pipeTriggerCmd "gitlab.com/gitlab-org/cli/commands/ci/trigger"
|
jobPlayCmd "gitlab.com/gitlab-org/cli/commands/ci/trigger"
|
||||||
ciViewCmd "gitlab.com/gitlab-org/cli/commands/ci/view"
|
ciViewCmd "gitlab.com/gitlab-org/cli/commands/ci/view"
|
||||||
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
|
||||||
|
@ -38,7 +39,8 @@ func NewCmdCI(f *cmdutils.Factory) *cobra.Command {
|
||||||
ciCmd.AddCommand(pipeStatusCmd.NewCmdStatus(f))
|
ciCmd.AddCommand(pipeStatusCmd.NewCmdStatus(f))
|
||||||
ciCmd.AddCommand(pipeRetryCmd.NewCmdRetry(f))
|
ciCmd.AddCommand(pipeRetryCmd.NewCmdRetry(f))
|
||||||
ciCmd.AddCommand(pipeRunCmd.NewCmdRun(f))
|
ciCmd.AddCommand(pipeRunCmd.NewCmdRun(f))
|
||||||
ciCmd.AddCommand(pipeTriggerCmd.NewCmdTrigger(f))
|
ciCmd.AddCommand(jobPlayCmd.NewCmdTrigger(f))
|
||||||
|
ciCmd.AddCommand(pipeRunTrigCmd.NewCmdRunTrig(f))
|
||||||
ciCmd.AddCommand(jobArtifactCmd.NewCmdRun(f))
|
ciCmd.AddCommand(jobArtifactCmd.NewCmdRun(f))
|
||||||
ciCmd.AddCommand(pipeGetCmd.NewCmdGet(f))
|
ciCmd.AddCommand(pipeGetCmd.NewCmdGet(f))
|
||||||
ciCmd.AddCommand(ciConfigCmd.NewCmdConfig(f))
|
ciCmd.AddCommand(ciConfigCmd.NewCmdConfig(f))
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
"gitlab.com/gitlab-org/cli/internal/glrepo"
|
"gitlab.com/gitlab-org/cli/internal/glrepo"
|
||||||
"gitlab.com/gitlab-org/cli/pkg/git"
|
"gitlab.com/gitlab-org/cli/pkg/git"
|
||||||
"gitlab.com/gitlab-org/cli/pkg/iostreams"
|
"gitlab.com/gitlab-org/cli/pkg/iostreams"
|
||||||
|
@ -179,6 +180,27 @@ func getPipelineId(inputs *JobInputs, opts *JobOptions) (int, error) {
|
||||||
return pipeline.ID, err
|
return pipeline.ID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetDefaultBranch(f *cmdutils.Factory) string {
|
||||||
|
repo, err := f.BaseRepo()
|
||||||
|
if err != nil {
|
||||||
|
return "master"
|
||||||
|
}
|
||||||
|
|
||||||
|
remotes, err := f.Remotes()
|
||||||
|
if err != nil {
|
||||||
|
return "master"
|
||||||
|
}
|
||||||
|
|
||||||
|
repoRemote, err := remotes.FindByRepo(repo.RepoOwner(), repo.RepoName())
|
||||||
|
if err != nil {
|
||||||
|
return "master"
|
||||||
|
}
|
||||||
|
|
||||||
|
branch, _ := git.GetDefaultBranch(repoRemote.Name)
|
||||||
|
|
||||||
|
return branch
|
||||||
|
}
|
||||||
|
|
||||||
func getBranch(branch string, opts *JobOptions) (string, error) {
|
func getBranch(branch string, opts *JobOptions) (string, error) {
|
||||||
if branch != "" {
|
if branch != "" {
|
||||||
return branch, nil
|
return branch, nil
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gitlab.com/gitlab-org/cli/api"
|
"gitlab.com/gitlab-org/cli/api"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/ci/ciutils"
|
||||||
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
"gitlab.com/gitlab-org/cli/pkg/git"
|
|
||||||
|
|
||||||
"github.com/MakeNowJust/heredoc"
|
"github.com/MakeNowJust/heredoc"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -22,27 +22,6 @@ var (
|
||||||
|
|
||||||
var envVariables = []string{}
|
var envVariables = []string{}
|
||||||
|
|
||||||
func getDefaultBranch(f *cmdutils.Factory) string {
|
|
||||||
repo, err := f.BaseRepo()
|
|
||||||
if err != nil {
|
|
||||||
return "master"
|
|
||||||
}
|
|
||||||
|
|
||||||
remotes, err := f.Remotes()
|
|
||||||
if err != nil {
|
|
||||||
return "master"
|
|
||||||
}
|
|
||||||
|
|
||||||
repoRemote, err := remotes.FindByRepo(repo.RepoOwner(), repo.RepoName())
|
|
||||||
if err != nil {
|
|
||||||
return "master"
|
|
||||||
}
|
|
||||||
|
|
||||||
branch, _ := git.GetDefaultBranch(repoRemote.Name)
|
|
||||||
|
|
||||||
return branch
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseVarArg(s string) (*gitlab.PipelineVariableOptions, error) {
|
func parseVarArg(s string) (*gitlab.PipelineVariableOptions, error) {
|
||||||
// From https://pkg.go.dev/strings#Split:
|
// From https://pkg.go.dev/strings#Split:
|
||||||
//
|
//
|
||||||
|
@ -167,7 +146,7 @@ func NewCmdRun(f *cmdutils.Factory) *cobra.Command {
|
||||||
} else {
|
} else {
|
||||||
// `ci run` is running out of a git repo
|
// `ci run` is running out of a git repo
|
||||||
fmt.Fprintln(f.IO.StdOut, "not in a git repository, using repository argument")
|
fmt.Fprintln(f.IO.StdOut, "not in a git repository, using repository argument")
|
||||||
c.Ref = gitlab.String(getDefaultBranch(f))
|
c.Ref = gitlab.String(ciutils.GetDefaultBranch(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
pipe, err := api.CreatePipeline(apiClient, repo.FullName(), c)
|
pipe, err := api.CreatePipeline(apiClient, repo.FullName(), c)
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package run_trig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"gitlab.com/gitlab-org/cli/api"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/ci/ciutils"
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdutils"
|
||||||
|
|
||||||
|
"github.com/MakeNowJust/heredoc"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/xanzy/go-gitlab"
|
||||||
|
)
|
||||||
|
|
||||||
|
var envVariables = []string{}
|
||||||
|
|
||||||
|
func parseVarArg(s string) (key string, val string, err error) {
|
||||||
|
// From https://pkg.go.dev/strings#Split:
|
||||||
|
//
|
||||||
|
// > If s does not contain sep and sep is not empty,
|
||||||
|
// > Split returns a slice of length 1 whose only element is s.
|
||||||
|
//
|
||||||
|
// Therefore, the function will always return a slice of min length 1.
|
||||||
|
v := strings.SplitN(s, ":", 2)
|
||||||
|
if len(v) == 1 {
|
||||||
|
return "", "", fmt.Errorf("invalid argument structure")
|
||||||
|
}
|
||||||
|
return v[0], v[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCmdRunTrig(f *cmdutils.Factory) *cobra.Command {
|
||||||
|
pipelineRunCmd := &cobra.Command{
|
||||||
|
Use: "run-trig [flags]",
|
||||||
|
Short: `Run a CI/CD pipeline trigger`,
|
||||||
|
Aliases: []string{"run-trig"},
|
||||||
|
Example: heredoc.Doc(`
|
||||||
|
glab ci run-trig -t xxxx
|
||||||
|
glab ci run-trig -t xxxx -b main
|
||||||
|
glab ci run-trig -t xxxx -b main --variables key1:val1
|
||||||
|
glab ci run-trig -t xxxx -b main --variables key1:val1,key2:val2
|
||||||
|
glab ci run-trig -t xxxx -b main --variables key1:val1 --variables key2:val2
|
||||||
|
`),
|
||||||
|
Long: ``,
|
||||||
|
Args: cobra.ExactArgs(0),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
apiClient, err := f.HttpClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
repo, err := f.BaseRepo()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := &gitlab.RunPipelineTriggerOptions{
|
||||||
|
Variables: make(map[string]string),
|
||||||
|
}
|
||||||
|
|
||||||
|
if customPipelineVars, _ := cmd.Flags().GetStringSlice("variables"); len(customPipelineVars) > 0 {
|
||||||
|
for _, v := range customPipelineVars {
|
||||||
|
key, val, err := parseVarArg(v)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parsing pipeline variable expected format KEY:VALUE: %w", err)
|
||||||
|
}
|
||||||
|
c.Variables[key] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
branch, err := cmd.Flags().GetString("branch")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if branch != "" {
|
||||||
|
c.Ref = gitlab.String(branch)
|
||||||
|
} else if currentBranch, err := f.Branch(); err == nil {
|
||||||
|
c.Ref = gitlab.String(currentBranch)
|
||||||
|
} else {
|
||||||
|
// `ci run-trig` is running out of a git repo
|
||||||
|
fmt.Fprintln(f.IO.StdOut, "not in a git repository, using repository argument")
|
||||||
|
c.Ref = gitlab.String(ciutils.GetDefaultBranch(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := cmd.Flags().GetString("token")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if token == "" {
|
||||||
|
token = os.Getenv("CI_JOB_TOKEN")
|
||||||
|
}
|
||||||
|
if token == "" {
|
||||||
|
return errors.New("--token parameter can be omitted only if CI_JOB_TOKEN environment variable is set")
|
||||||
|
}
|
||||||
|
c.Token = &token
|
||||||
|
|
||||||
|
pipe, err := api.RunPipelineTrigger(apiClient, repo.FullName(), c)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(f.IO.StdOut, "Created pipeline (id:", pipe.ID, "), status:", pipe.Status, ", ref:", pipe.Ref, ", weburl: ", pipe.WebURL, ")")
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pipelineRunCmd.Flags().StringP("token", "t", "", "Pipeline trigger token (can be omitted only if CI_JOB_TOKEN environment variable is set)")
|
||||||
|
pipelineRunCmd.Flags().StringP("branch", "b", "", "Create pipeline on branch/ref <string>")
|
||||||
|
pipelineRunCmd.Flags().StringSliceVarP(&envVariables, "variables", "", []string{}, "Pass variables to pipeline in format <key>:<value>")
|
||||||
|
|
||||||
|
return pipelineRunCmd
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
package run_trig
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gitlab.com/gitlab-org/cli/commands/cmdtest"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gitlab.com/gitlab-org/cli/pkg/httpmock"
|
||||||
|
"gitlab.com/gitlab-org/cli/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ResponseJSON struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
|
||||||
|
ios, _, stdout, stderr := cmdtest.InitIOStreams(isTTY, "")
|
||||||
|
|
||||||
|
factory := cmdtest.InitFactory(ios, rt)
|
||||||
|
|
||||||
|
factory.Branch = func() (string, error) {
|
||||||
|
return "custom-branch-123", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_, _ = factory.HttpClient()
|
||||||
|
|
||||||
|
cmd := NewCmdRunTrig(factory)
|
||||||
|
|
||||||
|
return cmdtest.ExecuteCommand(cmd, cli, stdout, stderr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCIRun(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
cli string
|
||||||
|
ciJobToken string
|
||||||
|
expectedPOSTBody string
|
||||||
|
expectedOut string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "when running `ci run-trig` without branch parameter, defaults to current branch",
|
||||||
|
cli: "-t foobar",
|
||||||
|
ciJobToken: "",
|
||||||
|
expectedPOSTBody: fmt.Sprintf(`"ref":"%s"`, "custom-branch-123"),
|
||||||
|
expectedOut: fmt.Sprintf("Created pipeline (id: 123 ), status: created , ref: %s , weburl: https://gitlab.com/OWNER/REPO/-/pipelines/123 )\n", "custom-branch-123"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "when running `ci run-trig` with branch parameter, run CI at branch",
|
||||||
|
cli: "-t foobar -b ci-cd-improvement-399",
|
||||||
|
ciJobToken: "",
|
||||||
|
expectedPOSTBody: `"ref":"ci-cd-improvement-399"`,
|
||||||
|
expectedOut: "Created pipeline (id: 123 ), status: created , ref: ci-cd-improvement-399 , weburl: https://gitlab.com/OWNER/REPO/-/pipelines/123 )\n",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "when running `ci run-trig` without any parameter, takes trigger token from env variable",
|
||||||
|
cli: "",
|
||||||
|
ciJobToken: "foobar",
|
||||||
|
expectedPOSTBody: fmt.Sprintf(`"ref":"%s"`, "custom-branch-123"),
|
||||||
|
expectedOut: fmt.Sprintf("Created pipeline (id: 123 ), status: created , ref: %s , weburl: https://gitlab.com/OWNER/REPO/-/pipelines/123 )\n", "custom-branch-123"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
fakeHTTP := &httpmock.Mocker{
|
||||||
|
MatchURL: httpmock.PathAndQuerystring,
|
||||||
|
}
|
||||||
|
defer fakeHTTP.Verify(t)
|
||||||
|
|
||||||
|
initialEnvValue := os.Getenv("CI_JOB_TOKEN")
|
||||||
|
os.Setenv("CI_JOB_TOKEN", tc.ciJobToken)
|
||||||
|
defer os.Setenv("CI_JOB_TOKEN", initialEnvValue)
|
||||||
|
|
||||||
|
fakeHTTP.RegisterResponder(http.MethodPost, "/api/v4/projects/OWNER/REPO/trigger/pipeline",
|
||||||
|
func(req *http.Request) (*http.Response, error) {
|
||||||
|
rb, _ := io.ReadAll(req.Body)
|
||||||
|
|
||||||
|
var response ResponseJSON
|
||||||
|
err := json.Unmarshal(rb, &response)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Error when parsing response body %s\n", rb)
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.Token != "foobar" {
|
||||||
|
fmt.Printf("Invalid token %s\n", rb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure CLI runs CI on correct branch
|
||||||
|
assert.Contains(t, string(rb), tc.expectedPOSTBody)
|
||||||
|
resp, _ := httpmock.NewStringResponse(http.StatusOK, fmt.Sprintf(`{
|
||||||
|
"id": 123,
|
||||||
|
"iid": 123,
|
||||||
|
"project_id": 3,
|
||||||
|
"status": "created",
|
||||||
|
"ref": "%s",
|
||||||
|
"web_url": "https://gitlab.com/OWNER/REPO/-/pipelines/123"}`, response.Ref))(req)
|
||||||
|
return resp, nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
output, _ := runCommand(fakeHTTP, false, tc.cli)
|
||||||
|
|
||||||
|
out := output.String()
|
||||||
|
|
||||||
|
assert.Equal(t, tc.expectedOut, out)
|
||||||
|
assert.Empty(t, output.Stderr())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,6 +43,7 @@ pipeline
|
||||||
- [`list`](list.md)
|
- [`list`](list.md)
|
||||||
- [`retry`](retry.md)
|
- [`retry`](retry.md)
|
||||||
- [`run`](run.md)
|
- [`run`](run.md)
|
||||||
|
- [`run-trig`](run-trig.md)
|
||||||
- [`status`](status.md)
|
- [`status`](status.md)
|
||||||
- [`trace`](trace.md)
|
- [`trace`](trace.md)
|
||||||
- [`trigger`](trigger.md)
|
- [`trigger`](trigger.md)
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
---
|
||||||
|
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
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This documentation is auto generated by a script.
|
||||||
|
Please do not edit this file directly. Run `make gen-docs` instead.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# `glab ci run-trig`
|
||||||
|
|
||||||
|
Run a CI/CD pipeline trigger
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
glab ci run-trig [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aliases
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
run-trig
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
glab ci run-trig -t xxxx
|
||||||
|
glab ci run-trig -t xxxx -b main
|
||||||
|
glab ci run-trig -t xxxx -b main --variables key1:val1
|
||||||
|
glab ci run-trig -t xxxx -b main --variables key1:val1,key2:val2
|
||||||
|
glab ci run-trig -t xxxx -b main --variables key1:val1 --variables key2:val2
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
```plaintext
|
||||||
|
-b, --branch string Create pipeline on branch/ref <string>
|
||||||
|
-t, --token string Pipeline trigger token (can be omitted only if CI_JOB_TOKEN environment variable is set)
|
||||||
|
--variables strings Pass variables to pipeline in format <key>:<value>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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
|
||||||
|
```
|
Loading…
Reference in New Issue