func (o Options) ExecuteProcess() (int, error) {
	if o.ArtifactDir != "" {
		if err := os.MkdirAll(o.ArtifactDir, os.ModePerm); err != nil {
			return InternalErrorCode, fmt.Errorf("could not create artifact directory(%s): %v", o.ArtifactDir, err)
		}
	}
	processLogFile, err := os.Create(o.ProcessLog)
	if err != nil {
		return InternalErrorCode, fmt.Errorf("could not create process logfile(%s): %v", o.ProcessLog, err)
	}
	defer processLogFile.Close()

	output := io.MultiWriter(os.Stdout, processLogFile)
	logrus.SetOutput(output)
	defer logrus.SetOutput(os.Stdout)

	// if we get asked to terminate we need to forward
	// that to the wrapped process as if it timed out
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

	if o.PreviousMarker != "" {
		ctx, cancel := context.WithCancel(context.Background())
		go func() {
			select {
			case s := <-interrupt:
				logrus.Errorf("Received interrupt %s, cancelling...", s)
				cancel()
			case <-ctx.Done():
			}
		}()
		code, err := wrapper.WaitForMarker(ctx, o.PreviousMarker)
		cancel() // end previous go-routine when not interrupted
		if err != nil {
			return InternalErrorCode, fmt.Errorf("wait for previous marker %s: %v", o.PreviousMarker, err)
		}
		if code != 0 {
			logrus.Infof("Skipping as previous step exited %d", code)
			return PreviousErrorCode, nil
		}
	}

	executable := o.Args[0]
	var arguments []string
	if len(o.Args) > 1 {
		arguments = o.Args[1:]
	}
	command := exec.Command(executable, arguments...)
	command.Stderr = output
	command.Stdout = output
	if err := command.Start(); err != nil {
		return InternalErrorCode, fmt.Errorf("could not start the process: %v", err)
	}

	timeout := optionOrDefault(o.Timeout, DefaultTimeout)
	gracePeriod := optionOrDefault(o.GracePeriod, DefaultGracePeriod)
	var commandErr error
	cancelled, aborted := false, false
	done := make(chan error)
	go func() {
		done <- command.Wait()
	}()
	select {
	case err := <-done:
		commandErr = err
	case <-time.After(timeout):
		logrus.Errorf("Process did not finish before %s timeout", timeout)
		cancelled = true
		gracefullyTerminate(command, done, gracePeriod)
	case s := <-interrupt:
		logrus.Errorf("Entrypoint received interrupt: %v", s)
		cancelled = true
		aborted = true
		gracefullyTerminate(command, done, gracePeriod)
	}

	var returnCode int
	if cancelled {
		if aborted {
			commandErr = errAborted
			returnCode = AbortedErrorCode
		} else {
			commandErr = errTimedOut
			returnCode = InternalErrorCode
		}
	} else {
		if status, ok := command.ProcessState.Sys().(syscall.WaitStatus); ok {
			returnCode = status.ExitStatus()
		} else if commandErr == nil {
			returnCode = 0
		} else {
			returnCode = 1
		}

		if returnCode != 0 {
			commandErr = fmt.Errorf("wrapped process failed: %v", commandErr)
		}
	}
	return returnCode, commandErr
}
func (o Options) ExecuteProcess() (int, error) {
	if o.ArtifactDir != "" {
		if err := os.MkdirAll(o.ArtifactDir, os.ModePerm); err != nil {
			return InternalErrorCode, fmt.Errorf("could not create artifact directory(%s): %v", o.ArtifactDir, err)
		}
	}
	processLogFile, err := os.Create(o.ProcessLog)
	if err != nil {
		return InternalErrorCode, fmt.Errorf("could not create process logfile(%s): %v", o.ProcessLog, err)
	}
	defer processLogFile.Close()

	output := io.MultiWriter(os.Stdout, processLogFile)
	logrus.SetOutput(output)
	defer logrus.SetOutput(os.Stdout)

	
	
	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)

	if o.PreviousMarker != "" {
		ctx, cancel := context.WithCancel(context.Background())
		go func() {
			select {
			case s := <-interrupt:
				logrus.Errorf("Received interrupt %s, cancelling...", s)
				cancel()
			case <-ctx.Done():
			}
		}()
		code, err := wrapper.WaitForMarker(ctx, o.PreviousMarker)
		cancel() 
		if err != nil {
			return InternalErrorCode, fmt.Errorf("wait for previous marker %s: %v", o.PreviousMarker, err)
		}
		if code != 0 {
			logrus.Infof("Skipping as previous step exited %d", code)
			return PreviousErrorCode, nil
		}
	}

	executable := o.Args[0]
	var arguments []string
	if len(o.Args) > 1 {
		arguments = o.Args[1:]
	}
	command := exec.Command(executable, arguments...)
	command.Stderr = output
	command.Stdout = output
	if err := command.Start(); err != nil {
		return InternalErrorCode, fmt.Errorf("could not start the process: %v", err)
	}

	timeout := optionOrDefault(o.Timeout, DefaultTimeout)
	gracePeriod := optionOrDefault(o.GracePeriod, DefaultGracePeriod)
	var commandErr error
	cancelled, aborted := false, false
	done := make(chan error)
	go func() {
		done <- command.Wait()
	}()
	select {
	case err := <-done:
		commandErr = err
	case <-time.After(timeout):
		logrus.Errorf("Process did not finish before %s timeout", timeout)
		cancelled = true
		gracefullyTerminate(command, done, gracePeriod)
	case s := <-interrupt:
		logrus.Errorf("Entrypoint received interrupt: %v", s)
		cancelled = true
		aborted = true
		gracefullyTerminate(command, done, gracePeriod)
	}

	var returnCode int
	if cancelled {
		if aborted {
			commandErr = errAborted
			returnCode = AbortedErrorCode
		} else {
			commandErr = errTimedOut
			returnCode = InternalErrorCode
		}
	} else {
		if status, ok := command.ProcessState.Sys().(syscall.WaitStatus); ok {
			returnCode = status.ExitStatus()
		} else if commandErr == nil {
			returnCode = 0
		} else {
			returnCode = 1
		}

		if returnCode != 0 {
			commandErr = fmt.Errorf("wrapped process failed: %v", commandErr)
		}
	}
	return returnCode, commandErr
}
func ( o Options ) ExecuteProcess ( ) ( int , error ) { if o . ArtifactDir != " " { if err := os . MkdirAll ( o . ArtifactDir , os . ModePerm ) ; err != nil { return InternalErrorCode , fmt . Errorf ( " " , o . ArtifactDir , err ) } } processLogFile , err := os . Create ( o . ProcessLog ) if err != nil { return InternalErrorCode , fmt . Errorf ( " " , o . ProcessLog , err ) } defer processLogFile . Close ( ) output := io . MultiWriter ( os . Stdout , processLogFile ) logrus . SetOutput ( output ) defer logrus . SetOutput ( os . Stdout ) // if we get asked to terminate we need to forward // that to the wrapped process as if it timed out interrupt := make ( chan os . Signal , 1 ) signal . Notify ( interrupt , os . Interrupt , syscall . SIGTERM ) if o . PreviousMarker != " " { ctx , cancel := context . WithCancel ( context . Background ( ) ) go func ( ) { select { case s := <- interrupt : logrus . Errorf ( " " , s ) cancel ( ) case <- ctx . Done ( ) : } } ( ) code , err := wrapper . WaitForMarker ( ctx , o . PreviousMarker ) cancel ( ) // end previous go-routine when not interrupted if err != nil { return InternalErrorCode , fmt . Errorf ( " " , o . PreviousMarker , err ) } if code != 0 { logrus . Infof ( " " , code ) return PreviousErrorCode , nil } } executable := o . Args [ 0 ] var arguments [ ] string if len ( o . Args ) > 1 { arguments = o . Args [ 1 : ] } command := exec . Command ( executable , arguments ... ) command . Stderr = output command . Stdout = output if err := command . Start ( ) ; err != nil { return InternalErrorCode , fmt . Errorf ( " " , err ) } timeout := optionOrDefault ( o . Timeout , DefaultTimeout ) gracePeriod := optionOrDefault ( o . GracePeriod , DefaultGracePeriod ) var commandErr error cancelled , aborted := false , false done := make ( chan error ) go func ( ) { done <- command . Wait ( ) } ( ) select { case err := <- done : commandErr = err case <- time . After ( timeout ) : logrus . Errorf ( " " , timeout ) cancelled = true gracefullyTerminate ( command , done , gracePeriod ) case s := <- interrupt : logrus . Errorf ( " " , s ) cancelled = true aborted = true gracefullyTerminate ( command , done , gracePeriod ) } var returnCode int if cancelled { if aborted { commandErr = errAborted returnCode = AbortedErrorCode } else { commandErr = errTimedOut returnCode = InternalErrorCode } } else { if status , ok := command . ProcessState . Sys ( ) . ( syscall . WaitStatus ) ; ok { returnCode = status . ExitStatus ( ) } else if commandErr == nil { returnCode = 0 } else { returnCode = 1 } if returnCode != 0 { commandErr = fmt . Errorf ( " " , commandErr ) } } return returnCode , commandErr }
// ExecuteProcess creates the artifact directory then executes the process as
// configured, writing the output to the process log.
ExecuteProcess creates the artifact directory then executes the process as configured writing the output to the process log .