1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-10-30 23:57:50 +02:00

solman upload go the step (#2522)

Upload content into a transport request via SOLMAN

Co-authored-by: Oliver Feldmann <oliver.feldmann@sap.com>
This commit is contained in:
Marcus Holl
2021-02-19 13:07:18 +01:00
committed by GitHub
parent 2d93e5d4df
commit 60feb3409f
10 changed files with 756 additions and 0 deletions

View File

@@ -68,6 +68,7 @@ func GetAllStepMetadata() map[string]config.StepData {
"containerSaveImage": containerSaveImageMetadata(),
"sonarExecuteScan": sonarExecuteScanMetadata(),
"transportRequestUploadCTS": transportRequestUploadCTSMetadata(),
"transportRequestUploadSOLMAN": transportRequestUploadSOLMANMetadata(),
"uiVeri5ExecuteTests": uiVeri5ExecuteTestsMetadata(),
"vaultRotateSecretId": vaultRotateSecretIdMetadata(),
"artifactPrepareVersion": artifactPrepareVersionMetadata(),

View File

@@ -128,6 +128,7 @@ func Execute() {
rootCmd.AddCommand(CheckChangeInDevelopmentCommand())
rootCmd.AddCommand(TransportRequestUploadCTSCommand())
rootCmd.AddCommand(IntegrationArtifactDeployCommand())
rootCmd.AddCommand(TransportRequestUploadSOLMANCommand())
rootCmd.AddCommand(IntegrationArtifactUpdateConfigurationCommand())
rootCmd.AddCommand(IntegrationArtifactGetMplStatusCommand())
rootCmd.AddCommand(IntegrationArtifactDownloadCommand())

View File

@@ -0,0 +1,83 @@
package cmd
import (
"github.com/SAP/jenkins-library/pkg/command"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/SAP/jenkins-library/pkg/transportrequest/solman"
)
type transportRequestUploadSOLMANUtils interface {
command.ExecRunner
FileExists(filename string) (bool, error)
GetExitCode() int
// Add more methods here, or embed additional interfaces, or remove/replace as required.
// The transportRequestUploadSOLMANUtils interface should be descriptive of your runtime dependencies,
// i.e. include everything you need to be able to mock in tests.
// Unit tests shall be executable in parallel (not depend on global state), and don't (re-)test dependencies.
}
type transportRequestUploadSOLMANUtilsBundle struct {
*command.Command
*piperutils.Files
// Embed more structs as necessary to implement methods or interfaces you add to transportRequestUploadSOLMANUtils.
// Structs embedded in this way must each have a unique set of methods attached.
// If there is no struct which implements the method you need, attach the method to
// transportRequestUploadSOLMANUtilsBundle and forward to the implementation of the dependency.
}
func newTransportRequestUploadSOLMANUtils() transportRequestUploadSOLMANUtils {
utils := transportRequestUploadSOLMANUtilsBundle{
Command: &command.Command{},
Files: &piperutils.Files{},
}
// Reroute command output to logging framework
utils.Stdout(log.Writer())
utils.Stderr(log.Writer())
return &utils
}
func transportRequestUploadSOLMAN(config transportRequestUploadSOLMANOptions, telemetryData *telemetry.CustomData) {
// Utils can be used wherever the command.ExecRunner interface is expected.
// It can also be used for example as a mavenExecRunner.
utils := newTransportRequestUploadSOLMANUtils()
// For HTTP calls import piperhttp "github.com/SAP/jenkins-library/pkg/http"
// and use a &piperhttp.Client{} in a custom system
// Example: step checkmarxExecuteScan.go
// Error situations should be bubbled up until they reach the line below which will then stop execution
// through the log.Entry().Fatal() call leading to an os.Exit(1) in the end.
err := runTransportRequestUploadSOLMAN(&config, &solman.UploadAction{}, telemetryData, utils)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runTransportRequestUploadSOLMAN(config *transportRequestUploadSOLMANOptions, action solman.Action, telemetryData *telemetry.CustomData, utils transportRequestUploadSOLMANUtils) error {
action.WithConnection(solman.Connection{
Endpoint: config.Endpoint,
User: config.Username,
Password: config.Password,
})
action.WithChangeDocumentID(config.ChangeDocumentID)
action.WithTransportRequestID(config.TransportRequestID)
action.WithApplicationID(config.ApplicationID)
action.WithFile(config.FilePath)
action.WithCMOpts(config.CmClientOpts)
err := action.Perform(utils, utils)
if err == nil {
log.Entry().Infof("Upload of artifact '%s' to SAP Solution Manager succeeded (ChangeDocumentId: '%s', TransportRequestId: '%s').",
config.FilePath,
config.ChangeDocumentID,
config.TransportRequestID,
)
}
return err
}

View File

@@ -0,0 +1,195 @@
// Code generated by piper's step-generator. DO NOT EDIT.
package cmd
import (
"fmt"
"os"
"time"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/spf13/cobra"
)
type transportRequestUploadSOLMANOptions struct {
Endpoint string `json:"endpoint,omitempty"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
ApplicationID string `json:"applicationId,omitempty"`
ChangeDocumentID string `json:"changeDocumentId,omitempty"`
TransportRequestID string `json:"transportRequestId,omitempty"`
FilePath string `json:"filePath,omitempty"`
CmClientOpts []string `json:"cmClientOpts,omitempty"`
}
// TransportRequestUploadSOLMANCommand Uploads content to a transport request
func TransportRequestUploadSOLMANCommand() *cobra.Command {
const STEP_NAME = "transportRequestUploadSOLMAN"
metadata := transportRequestUploadSOLMANMetadata()
var stepConfig transportRequestUploadSOLMANOptions
var startTime time.Time
var createTransportRequestUploadSOLMANCmd = &cobra.Command{
Use: STEP_NAME,
Short: "Uploads content to a transport request",
Long: `Uploads content to a transport request which is associated with a change document in SAP Solution Manager`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
startTime = time.Now()
log.SetStepName(STEP_NAME)
log.SetVerbose(GeneralConfig.Verbose)
path, _ := os.Getwd()
fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
log.RegisterHook(fatalHook)
err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return err
}
log.RegisterSecret(stepConfig.Username)
log.RegisterSecret(stepConfig.Password)
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
log.RegisterHook(&sentryHook)
}
return nil
},
Run: func(_ *cobra.Command, _ []string) {
telemetryData := telemetry.CustomData{}
telemetryData.ErrorCode = "1"
handler := func() {
config.RemoveVaultSecretFiles()
telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
telemetryData.ErrorCategory = log.GetErrorCategory().String()
telemetry.Send(&telemetryData)
}
log.DeferExitHandler(handler)
defer handler()
telemetry.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
transportRequestUploadSOLMAN(stepConfig, &telemetryData)
telemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
}
addTransportRequestUploadSOLMANFlags(createTransportRequestUploadSOLMANCmd, &stepConfig)
return createTransportRequestUploadSOLMANCmd
}
func addTransportRequestUploadSOLMANFlags(cmd *cobra.Command, stepConfig *transportRequestUploadSOLMANOptions) {
cmd.Flags().StringVar(&stepConfig.Endpoint, "endpoint", os.Getenv("PIPER_endpoint"), "Service endpoint")
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "Operating system user for triggering the deployment")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password for the deploy user")
cmd.Flags().StringVar(&stepConfig.ApplicationID, "applicationId", os.Getenv("PIPER_applicationId"), "Id of the application.")
cmd.Flags().StringVar(&stepConfig.ChangeDocumentID, "changeDocumentId", os.Getenv("PIPER_changeDocumentId"), "Id of the change document to upload the file. This parameter is only taken into account when provided via signature to the step.")
cmd.Flags().StringVar(&stepConfig.TransportRequestID, "transportRequestId", os.Getenv("PIPER_transportRequestId"), "Id of the transport request to upload the file. This parameter is only taken into account when provided via signature to the step.")
cmd.Flags().StringVar(&stepConfig.FilePath, "filePath", os.Getenv("PIPER_filePath"), "Name/Path of the file which should be uploaded")
cmd.Flags().StringSliceVar(&stepConfig.CmClientOpts, "cmClientOpts", []string{}, "Additional options handed over to the cm client")
cmd.MarkFlagRequired("endpoint")
cmd.MarkFlagRequired("username")
cmd.MarkFlagRequired("password")
cmd.MarkFlagRequired("applicationId")
cmd.MarkFlagRequired("changeDocumentId")
cmd.MarkFlagRequired("transportRequestId")
cmd.MarkFlagRequired("filePath")
cmd.MarkFlagRequired("cmClientOpts")
}
// retrieve step metadata
func transportRequestUploadSOLMANMetadata() config.StepData {
var theMetaData = config.StepData{
Metadata: config.StepMetadata{
Name: "transportRequestUploadSOLMAN",
Aliases: []config.Alias{{Name: "transportRequestUploadFile", Deprecated: false}},
Description: "Uploads content to a transport request",
},
Spec: config.StepSpec{
Inputs: config.StepInputs{
Parameters: []config.StepParameters{
{
Name: "endpoint",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{{Name: "changeManagement/endpoint"}},
},
{
Name: "username",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "password",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "applicationId",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "changeDocumentId",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "transportRequestId",
ResourceRef: []config.ResourceReference{
{
Name: "commonPipelineEnvironment",
Param: "custom/transportRequestId",
},
},
Scope: []string{"PARAMETERS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "filePath",
ResourceRef: []config.ResourceReference{
{
Name: "commonPipelineEnvironment",
Param: "mtarFilePath",
},
},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "cmClientOpts",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEP", "GENERAL"},
Type: "[]string",
Mandatory: true,
Aliases: []config.Alias{{Name: "clientOpts"}, {Name: "changeManagement/clientOpts"}},
},
},
},
},
}
return theMetaData
}

View File

@@ -0,0 +1,17 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestTransportRequestUploadSOLMANCommand(t *testing.T) {
t.Parallel()
testCmd := TransportRequestUploadSOLMANCommand()
// only high level testing performed - details are tested in step generation procedure
assert.Equal(t, "transportRequestUploadSOLMAN", testCmd.Use, "command name incorrect")
}

View File

@@ -0,0 +1,103 @@
package cmd
import (
"fmt"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/SAP/jenkins-library/pkg/transportrequest/solman"
"github.com/stretchr/testify/assert"
"testing"
)
type transportRequestUploadSOLMANMockUtils struct {
*mock.ExecMockRunner
*mock.FilesMock
}
func newTransportRequestUploadSOLMANTestsUtils() transportRequestUploadSOLMANMockUtils {
utils := transportRequestUploadSOLMANMockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
}
return utils
}
type ActionMock struct {
received solman.UploadAction
performCalled bool
failWith error
}
func (a *ActionMock) WithConnection(c solman.Connection) {
a.received.Connection = c
}
func (a *ActionMock) WithChangeDocumentID(id string) {
a.received.ChangeDocumentID = id
}
func (a *ActionMock) WithTransportRequestID(id string) {
a.received.TransportRequestID = id
}
func (a *ActionMock) WithApplicationID(id string) {
a.received.ApplicationID = id
}
func (a *ActionMock) WithFile(f string) {
a.received.File = f
}
func (a *ActionMock) WithCMOpts(opts []string) {
a.received.CMOpts = opts
}
func (a *ActionMock) Perform(fs solman.FileSystem, command solman.Exec) error {
a.performCalled = true
return a.failWith
}
func TestRunTransportRequestUploadSOLMAN(t *testing.T) {
t.Parallel()
t.Run("solmand upload", func(t *testing.T) {
t.Parallel()
config := transportRequestUploadSOLMANOptions{
Endpoint: "https://example.org/solman",
Username: "me",
Password: "********",
ApplicationID: "XYZ",
ChangeDocumentID: "12345678",
TransportRequestID: "87654321",
FilePath: "myApp.xxx",
CmClientOpts: []string{"-Dtest=abc123"},
}
t.Run("straight forward", func(t *testing.T) {
utils := newTransportRequestUploadSOLMANTestsUtils()
action := ActionMock{}
err := runTransportRequestUploadSOLMAN(&config, &action, nil, utils)
if assert.NoError(t, err) {
assert.Equal(t, action.received, solman.UploadAction{
Connection: solman.Connection{
Endpoint: "https://example.org/solman",
User: "me",
Password: "********",
},
ApplicationID: "XYZ",
ChangeDocumentID: "12345678",
TransportRequestID: "87654321",
File: "myApp.xxx",
CMOpts: []string{"-Dtest=abc123"},
})
assert.True(t, action.performCalled)
}
})
t.Run("Error during deployment", func(t *testing.T) {
utils := newTransportRequestUploadSOLMANTestsUtils()
action := ActionMock{failWith: fmt.Errorf("upload failed")}
err := runTransportRequestUploadSOLMAN(&config, &action, nil, utils)
assert.Error(t, err, "upload failed")
})
})
}

View File

@@ -0,0 +1,19 @@
package solman
import (
"github.com/SAP/jenkins-library/pkg/command"
)
// Exec interface collecting everything which is execution related
// and needed in the context of a SOLMAN upload.
type Exec interface {
command.ExecRunner
GetExitCode() int
}
// Connection Everything we need for connecting to CTS
type Connection struct {
Endpoint string
User string
Password string
}

View File

@@ -0,0 +1,137 @@
package solman
import (
"fmt"
"github.com/SAP/jenkins-library/pkg/config/validation"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/pkg/errors"
"strings"
)
// FileSystem interface collecting everything which is file system
// related and needed in the context of a SOLMAN upload.
type FileSystem interface {
FileExists(path string) (bool, error)
}
// UploadAction Collects all the properties we need for the deployment
type UploadAction struct {
Connection Connection
ChangeDocumentID string
TransportRequestID string
ApplicationID string
File string
CMOpts []string
}
// Action collects everything which is needed to perform a SOLMAN upload
type Action interface {
WithConnection(Connection)
WithChangeDocumentID(string)
WithTransportRequestID(string)
WithApplicationID(string)
WithFile(string)
WithCMOpts([]string)
Perform(fs FileSystem, command Exec) error
}
// WithConnection specifies all the connection details which
// are required in order to connect to SOLMAN
func (a *UploadAction) WithConnection(c Connection) {
a.Connection = c
}
// WithChangeDocumentID specifies the change document which
// receives the executable.
func (a *UploadAction) WithChangeDocumentID(id string) {
a.ChangeDocumentID = id
}
// WithTransportRequestID specifies the transport request which
// receives the executable.
func (a *UploadAction) WithTransportRequestID(id string) {
a.TransportRequestID = id
}
// WithApplicationID specifies the application ID.
func (a *UploadAction) WithApplicationID(id string) {
a.ApplicationID = id
}
// WithFile specifies the executable which should be uploaded into
// a transport on SOLMAN
func (a *UploadAction) WithFile(f string) {
a.File = f
}
// WithCMOpts sets additional options for calling the
// cm client tool. E.g. -D options. Useful for troubleshooting
func (a *UploadAction) WithCMOpts(opts []string) {
a.CMOpts = opts
}
// Perform performs the SOLMAN upload
func (a *UploadAction) Perform(fs FileSystem, command Exec) error {
log.Entry().Infof("Deploying artifact '%s' to '%s'.",
a.File, a.Connection.Endpoint)
missingParameters, err := validation.FindEmptyStringsInConfigStruct(*a)
if err == nil {
notInitialized := len(missingParameters) != 0
if notInitialized {
err = fmt.Errorf("the following parameters are not available '%s'", missingParameters)
}
}
if err == nil {
var exists bool
exists, err = fs.FileExists(a.File)
if err == nil && !exists {
err = fmt.Errorf("file '%s' does not exist", a.File)
}
}
if err == nil {
if len(a.CMOpts) > 0 {
command.SetEnv([]string{fmt.Sprintf("CMCLIENT_OPTS=%s", strings.Join(a.CMOpts, " "))})
}
err = command.RunExecutable("cmclient",
"--endpoint", a.Connection.Endpoint,
"--user", a.Connection.User,
"--password", a.Connection.Password,
"--backend-type", "SOLMAN",
"upload-file-to-transport",
"-cID", a.ChangeDocumentID,
"-tID", a.TransportRequestID,
a.ApplicationID, a.File)
exitCode := command.GetExitCode()
if exitCode != 0 {
message := fmt.Sprintf("upload command returned with exit code '%d'", exitCode)
if err != nil {
// Using the wrapping here is to some extend an abuse, since it is not really
// error chaining (the other error is not necessaryly a "predecessor" of this one).
// But it is a pragmatic approach for not loosing information for trouble shooting. There
// is no possibility to have something like suppressed errors.
err = errors.Wrap(err, message)
} else {
err = errors.New(message)
}
}
}
if err == nil {
log.Entry().Infof("Deployment succeeded, artifact: '%s', endpoint: '%s'",
a.File, a.Connection.Endpoint)
} else {
log.Entry().WithError(err).Warnf("Deployment failed, artifact: '%s', endpoint: '%s'",
a.File, a.Connection.Endpoint)
}
return errors.Wrapf(err, "cannot upload artifact '%s'", a.File)
}

View File

@@ -0,0 +1,108 @@
package solman
import (
"fmt"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
"testing"
)
func TestSolmanUpload(t *testing.T) {
f := &mock.FilesMock{}
f.AddFile("myDeployable.xxx", []byte(""))
defaultUploadAction := UploadAction{}
defaultUploadAction.WithConnection(
Connection{
Endpoint: "https://example.org/solman",
User: "me",
Password: "******",
})
defaultUploadAction.WithChangeDocumentID("123456")
defaultUploadAction.WithTransportRequestID("000K11111111")
defaultUploadAction.WithApplicationID("MY_APP")
defaultUploadAction.WithFile("myDeployable.xxx")
defaultUploadAction.WithCMOpts([]string{"-Dmyprop1=abc", "-Dmyprop2=def"})
t.Run("Deployable does not exist", func(t *testing.T) {
uploadActionFileMissing := defaultUploadAction
uploadActionFileMissing.WithFile("myMissingDeployable.xxx")
e := &mock.ExecMockRunner{}
err := uploadActionFileMissing.Perform(f, e)
assert.EqualError(t, err, "cannot upload artifact 'myMissingDeployable.xxx': file 'myMissingDeployable.xxx' does not exist")
})
t.Run("Straight forward", func(t *testing.T) {
e := &mock.ExecMockRunner{}
err := defaultUploadAction.Perform(f, e)
if assert.NoError(t, err) {
assert.Len(t, e.Calls, 1)
assert.Equal(t, mock.ExecCall{
Exec: "cmclient",
Params: []string{
"--endpoint", "https://example.org/solman",
"--user", "me",
"--password", "******",
"--backend-type", "SOLMAN",
"upload-file-to-transport",
"-cID", "123456",
"-tID", "000K11111111",
"MY_APP",
"myDeployable.xxx",
},
}, e.Calls[0])
assert.Equal(t, []string{"CMCLIENT_OPTS=-Dmyprop1=abc -Dmyprop2=def"}, e.Env)
}
})
t.Run("Missing parameters", func(t *testing.T) {
e := &mock.ExecMockRunner{}
uploadAction := defaultUploadAction
uploadAction.WithConnection(
Connection{
Endpoint: "",
User: "me",
Password: "******",
},
)
uploadAction.WithTransportRequestID("")
err := uploadAction.Perform(f, e)
if assert.Error(t, err) {
// we should not rely on the order of the missing parameters
assert.Contains(t, err.Error(), "cannot upload artifact 'myDeployable.xxx': the following parameters are not available")
assert.Contains(t, err.Error(), "Connection.Endpoint")
assert.Contains(t, err.Error(), "TransportRequestID")
}
})
t.Run("Deploy command returns with return code not equal zero", func(t *testing.T) {
e := &mock.ExecMockRunner{}
e.ExitCode = 1
err := defaultUploadAction.Perform(f, e)
assert.EqualError(t, err, "cannot upload artifact 'myDeployable.xxx': upload command returned with exit code '1'")
})
t.Run("Deploy command cannot be executed", func(t *testing.T) {
e := &mock.ExecMockRunner{
ShouldFailOnCommand: map[string]error{
"cmclient.*": fmt.Errorf("cannot execute upload command"),
},
}
err := defaultUploadAction.Perform(f, e)
assert.EqualError(t, err, "cannot upload artifact 'myDeployable.xxx': cannot execute upload command")
})
}

View File

@@ -0,0 +1,92 @@
metadata:
name: transportRequestUploadSOLMAN
aliases:
- name: transportRequestUploadFile
description: "Uploads content to a transport request"
longDescription: |
Uploads content to a transport request which is associated with a change document in SAP Solution Manager
spec:
inputs:
secrets:
- name: uploadCredentialsId
description: Jenkins 'Username with password' credentials ID containing user and password to authenticate against the ABAP backend.
type: jenkins
aliases:
- name: changeManagement/credentialsId
params:
- name: endpoint
type: string
mandatory: true
description: "Service endpoint"
aliases:
- name: changeManagement/endpoint
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
- name: username
type: string
mandatory: true
description: "Operating system user for triggering the deployment"
secret: true
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
- name: password
type: string
mandatory: true
description: "Password for the deploy user"
secret: true
scope:
- PARAMETERS
- name: applicationId
type: string
mandatory: true
description: "Id of the application."
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
- name: changeDocumentId
type: string
mandatory: true
description: "Id of the change document to upload the file. This parameter is only taken into account when provided via signature to the step."
scope:
- PARAMETERS
- name: transportRequestId
resourceRef:
- name: commonPipelineEnvironment
param: custom/transportRequestId
type: string
mandatory: true
description: "Id of the transport request to upload the file. This parameter is only taken into account when provided via signature to the step."
scope:
- PARAMETERS
- name: filePath
resourceRef:
- name: commonPipelineEnvironment
param: mtarFilePath
type: string
mandatory: true
description: "Name/Path of the file which should be uploaded"
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
- name: cmClientOpts
aliases:
- name: clientOpts
- name: changeManagement/clientOpts
type: "[]string"
mandatory: true
description: "Additional options handed over to the cm client"
scope:
- PARAMETERS
- STAGES
- STEP
- GENERAL