gitlab.com/jfprevost/gitlab-runner-notlscheck@v11.11.4+incompatible/commands/exec.go (about)

     1  package commands
     2  
     3  import (
     4  	"os"
     5  	"os/exec"
     6  	"strings"
     7  
     8  	"github.com/sirupsen/logrus"
     9  	"github.com/urfave/cli"
    10  	"gitlab.com/ayufan/golang-cli-helpers"
    11  	"gitlab.com/gitlab-org/gitlab-runner/common"
    12  	"gitlab.com/gitlab-org/gitlab-runner/helpers/gitlab_ci_yaml_parser"
    13  
    14  	// Force to load all executors, executes init() on them
    15  	_ "gitlab.com/gitlab-org/gitlab-runner/executors/docker"
    16  	_ "gitlab.com/gitlab-org/gitlab-runner/executors/parallels"
    17  	_ "gitlab.com/gitlab-org/gitlab-runner/executors/shell"
    18  	_ "gitlab.com/gitlab-org/gitlab-runner/executors/ssh"
    19  	_ "gitlab.com/gitlab-org/gitlab-runner/executors/virtualbox"
    20  )
    21  
    22  type ExecCommand struct {
    23  	common.RunnerSettings
    24  	Job     string
    25  	Timeout int `long:"timeout" description:"Job execution timeout (in seconds)"`
    26  }
    27  
    28  func (c *ExecCommand) runCommand(name string, arg ...string) (string, error) {
    29  	cmd := exec.Command(name, arg...)
    30  	cmd.Env = os.Environ()
    31  	cmd.Stderr = os.Stderr
    32  	result, err := cmd.Output()
    33  	return string(result), err
    34  }
    35  
    36  func (c *ExecCommand) createBuild(repoURL string, abortSignal chan os.Signal) (build *common.Build, err error) {
    37  	// Check if we have uncommitted changes
    38  	_, err = c.runCommand("git", "diff", "--quiet", "HEAD")
    39  	if err != nil {
    40  		logrus.Warningln("You most probably have uncommitted changes.")
    41  		logrus.Warningln("These changes will not be tested.")
    42  	}
    43  
    44  	// Parse Git settings
    45  	sha, err := c.runCommand("git", "rev-parse", "HEAD")
    46  	if err != nil {
    47  		return
    48  	}
    49  
    50  	beforeSha, err := c.runCommand("git", "rev-parse", "HEAD~1")
    51  	if err != nil {
    52  		beforeSha = "0000000000000000000000000000000000000000"
    53  	}
    54  
    55  	refName, err := c.runCommand("git", "rev-parse", "--abbrev-ref", "HEAD")
    56  	if err != nil {
    57  		return
    58  	}
    59  
    60  	jobResponse := common.JobResponse{
    61  		ID:            1,
    62  		Token:         "",
    63  		AllowGitFetch: false,
    64  		JobInfo: common.JobInfo{
    65  			Name:        "",
    66  			Stage:       "",
    67  			ProjectID:   1,
    68  			ProjectName: "",
    69  		},
    70  		GitInfo: common.GitInfo{
    71  			RepoURL:   repoURL,
    72  			Ref:       strings.TrimSpace(refName),
    73  			Sha:       strings.TrimSpace(sha),
    74  			BeforeSha: strings.TrimSpace(beforeSha),
    75  		},
    76  		RunnerInfo: common.RunnerInfo{
    77  			Timeout: c.getTimeout(),
    78  		},
    79  	}
    80  
    81  	runner := &common.RunnerConfig{
    82  		RunnerSettings: c.RunnerSettings,
    83  	}
    84  
    85  	build, err = common.NewBuild(jobResponse, runner, abortSignal, nil)
    86  
    87  	return
    88  }
    89  
    90  func (c *ExecCommand) getTimeout() int {
    91  	if c.Timeout > 0 {
    92  		return c.Timeout
    93  	}
    94  
    95  	return common.DefaultExecTimeout
    96  }
    97  
    98  func (c *ExecCommand) Execute(context *cli.Context) {
    99  	wd, err := os.Getwd()
   100  	if err != nil {
   101  		logrus.Fatalln(err)
   102  	}
   103  
   104  	switch len(context.Args()) {
   105  	case 1:
   106  		c.Job = context.Args().Get(0)
   107  	default:
   108  		cli.ShowSubcommandHelp(context)
   109  		os.Exit(1)
   110  		return
   111  	}
   112  
   113  	c.Executor = context.Command.Name
   114  
   115  	abortSignal := make(chan os.Signal)
   116  	doneSignal := make(chan int, 1)
   117  
   118  	go waitForInterrupts(nil, abortSignal, doneSignal, nil)
   119  
   120  	// Add self-volume to docker
   121  	if c.RunnerSettings.Docker == nil {
   122  		c.RunnerSettings.Docker = &common.DockerConfig{}
   123  	}
   124  	c.RunnerSettings.Docker.Volumes = append(c.RunnerSettings.Docker.Volumes, wd+":"+wd+":ro")
   125  
   126  	// Create build
   127  	build, err := c.createBuild(wd, abortSignal)
   128  	if err != nil {
   129  		logrus.Fatalln(err)
   130  	}
   131  
   132  	parser := gitlab_ci_yaml_parser.NewGitLabCiYamlParser(c.Job)
   133  	err = parser.ParseYaml(&build.JobResponse)
   134  	if err != nil {
   135  		logrus.Fatalln(err)
   136  	}
   137  
   138  	err = build.Run(&common.Config{}, &common.Trace{Writer: os.Stdout})
   139  	if err != nil {
   140  		logrus.Fatalln(err)
   141  	}
   142  }
   143  
   144  func init() {
   145  	cmd := &ExecCommand{}
   146  
   147  	flags := clihelpers.GetFlagsFromStruct(cmd)
   148  	cliCmd := cli.Command{
   149  		Name:  "exec",
   150  		Usage: "execute a build locally",
   151  	}
   152  
   153  	for _, executor := range common.GetExecutors() {
   154  		subCmd := cli.Command{
   155  			Name:   executor,
   156  			Usage:  "use " + executor + " executor",
   157  			Action: cmd.Execute,
   158  			Flags:  flags,
   159  		}
   160  		cliCmd.Subcommands = append(cliCmd.Subcommands, subCmd)
   161  	}
   162  
   163  	common.RegisterCommand(cliCmd)
   164  }