func (b *CmdShell) writeCloneCmd(w io.Writer, build *common.Build) { dir := filepath.FromSlash(build.FullProjectDir()) b.writeCommand(w, "echo Clonning repository...") b.writeCommandChecked(w, "rd /s /q \"%s\" 2> NUL 1>NUL", dir) b.writeCommandChecked(w, "git clone \"%s\" \"%s\"", build.RepoURL, dir) b.writeCommandChecked(w, "cd \"%s\"", dir) }
func (b *PowerShell) writeCloneCmd(w io.Writer, build *common.Build) { dir := filepath.FromSlash(build.FullProjectDir()) b.writeCommand(w, "echo \"Clonning repository...\"") b.writeCommandChecked(w, "if(Test-Path \"%s\") { Remove-Item -Force -Recurse \"%s\" }", dir, dir) b.writeCommandChecked(w, "git clone \"%s\" \"%s\"", build.RepoURL, dir) b.writeCommandChecked(w, "cd \"%s\"", dir) }
func (mr *RunCommand) addBuild(newBuild *common.Build) { mr.buildsLock.Lock() defer mr.buildsLock.Unlock() newBuild.AssignID(mr.builds...) mr.builds = append(mr.builds, newBuild) mr.debugln("Added a new build", newBuild) }
func (b *BashShell) writeFetchCmd(w io.Writer, build *common.Build) { io.WriteString(w, fmt.Sprintf("if [[ -d %s/.git ]]; then\n", build.FullProjectDir())) io.WriteString(w, "echo Fetching changes...\n") io.WriteString(w, fmt.Sprintf("cd %s\n", build.FullProjectDir())) io.WriteString(w, fmt.Sprintf("git clean -fdx\n")) io.WriteString(w, fmt.Sprintf("git reset --hard > /dev/null\n")) io.WriteString(w, fmt.Sprintf("git remote set-url origin %s\n", build.RepoURL)) io.WriteString(w, fmt.Sprintf("git fetch origin\n")) io.WriteString(w, fmt.Sprintf("else\n")) b.writeCloneCmd(w, build) io.WriteString(w, fmt.Sprintf("fi\n")) }
func (b *CmdShell) writeFetchCmd(w io.Writer, build *common.Build) { dir := filepath.FromSlash(build.FullProjectDir()) b.writeCommand(w, "IF EXIST \"%s\\.git\" (", dir) b.writeCommand(w, "echo Fetching changes...") b.writeCommandChecked(w, "cd \"%s\"", dir) b.writeCommandChecked(w, "git clean -fdx") b.writeCommandChecked(w, "git reset --hard > NUL") b.writeCommandChecked(w, "git remote set-url origin \"%s\"", build.RepoURL) b.writeCommandChecked(w, "git fetch origin") b.writeCommand(w, ") ELSE (") b.writeCloneCmd(w, build) b.writeCommand(w, ")") }
func (b *PowerShell) writeFetchCmd(w io.Writer, build *common.Build) { dir := filepath.FromSlash(build.FullProjectDir()) b.writeCommand(w, "if(Test-Path \"%s\\.git\") {", dir) b.writeCommand(w, "echo \"Fetching changes...\"") b.writeCommandChecked(w, "cd \"%s\"", dir) b.writeCommandChecked(w, "git clean -fdx") b.writeCommandChecked(w, "git reset --hard > $null") b.writeCommandChecked(w, "git remote set-url origin \"%s\"", build.RepoURL) b.writeCommandChecked(w, "git fetch origin") b.writeCommand(w, "} else {") b.writeCloneCmd(w, build) b.writeCommand(w, "}") }
func (b *BashShell) writeCloneCmd(w io.Writer, build *common.Build) { io.WriteString(w, "echo Clonning repository...\n") io.WriteString(w, fmt.Sprintf("rm -rf %s\n", build.FullProjectDir())) io.WriteString(w, fmt.Sprintf("mkdir -p %s\n", build.FullProjectDir())) io.WriteString(w, fmt.Sprintf("git clone %s %s\n", build.RepoURL, build.FullProjectDir())) io.WriteString(w, fmt.Sprintf("cd %s\n", build.FullProjectDir())) }
func (b *PowerShell) GenerateScript(build *common.Build, shellType common.ShellType) (*common.ShellScript, error) { var buffer bytes.Buffer w := bufio.NewWriter(&buffer) projectDir := build.FullProjectDir() projectDir = helpers.ToBackslash(projectDir) b.writeCommand(w, "$ErrorActionPreference = \"Stop\"") if len(build.Hostname) != 0 { b.writeCommand(w, "echo \"Running on $env:computername via %s...\"", helpers.ShellEscape(build.Hostname)) } else { b.writeCommand(w, "echo \"Running on $env:computername...\"") } b.writeCommand(w, "") if build.AllowGitFetch { b.writeFetchCmd(w, build, projectDir) } else { b.writeCloneCmd(w, build, projectDir) } b.writeCheckoutCmd(w, build) b.writeCommand(w, "") for _, command := range strings.Split(build.Commands, "\n") { command = strings.TrimRight(command, " \t\r\n") if strings.TrimSpace(command) == "" { b.writeCommand(w, "echo \"\"") continue } if !helpers.BoolOrDefault(build.Runner.DisableVerbose, false) { b.writeCommand(w, "echo \"%s\"", command) } b.writeCommandChecked(w, "%s", command) } w.Flush() env := []string{ fmt.Sprintf("CI_BUILD_REF=%s", build.Sha), fmt.Sprintf("CI_BUILD_BEFORE_SHA=%s", build.BeforeSha), fmt.Sprintf("CI_BUILD_REF_NAME=%s", build.RefName), fmt.Sprintf("CI_BUILD_ID=%d", build.ID), fmt.Sprintf("CI_BUILD_REPO=%s", build.RepoURL), fmt.Sprintf("CI_PROJECT_ID=%d", build.ProjectID), fmt.Sprintf("CI_PROJECT_DIR=%s", projectDir), "CI=true", "CI_SERVER=yes", "CI_SERVER_NAME=GitLab CI", "CI_SERVER_VERSION=", "CI_SERVER_REVISION=", "GITLAB_CI=true", } script := common.ShellScript{ Environment: env, Script: buffer.Bytes(), Command: "powershell", Arguments: []string{"-noprofile", "-noninteractive", "-executionpolicy", "Bypass", "-command"}, PassFile: true, Extension: "ps1", } return &script, nil }
func (b *BashShell) GenerateScript(build *common.Build, shellType common.ShellType) (*common.ShellScript, error) { var buffer bytes.Buffer w := bufio.NewWriter(&buffer) io.WriteString(w, "#!/usr/bin/env bash\n") io.WriteString(w, "\n") if len(build.Hostname) != 0 { io.WriteString(w, fmt.Sprintf("echo Running on $(hostname) via %s...\n", helpers.ShellEscape(build.Hostname))) } else { io.WriteString(w, "echo Running on $(hostname)...\n") } io.WriteString(w, "\n") io.WriteString(w, "set -eo pipefail\n") io.WriteString(w, "\n") if build.AllowGitFetch { b.writeFetchCmd(w, build) } else { b.writeCloneCmd(w, build) } b.writeCheckoutCmd(w, build) io.WriteString(w, "\n") if !helpers.BoolOrDefault(build.Runner.DisableVerbose, false) { io.WriteString(w, "set -v\n") io.WriteString(w, "\n") } commands := build.Commands commands = strings.Replace(commands, "\r\n", "\n", -1) io.WriteString(w, commands) w.Flush() env := []string{ fmt.Sprintf("CI_BUILD_REF=%s", build.Sha), fmt.Sprintf("CI_BUILD_BEFORE_SHA=%s", build.BeforeSha), fmt.Sprintf("CI_BUILD_REF_NAME=%s", build.RefName), fmt.Sprintf("CI_BUILD_ID=%d", build.ID), fmt.Sprintf("CI_BUILD_REPO=%s", build.RepoURL), fmt.Sprintf("CI_PROJECT_ID=%d", build.ProjectID), fmt.Sprintf("CI_PROJECT_DIR=%s", build.FullProjectDir()), "CI_SERVER=yes", "CI_SERVER_NAME=GitLab CI", "CI_SERVER_VERSION=", "CI_SERVER_REVISION=", } script := common.ShellScript{ Environment: env, Script: buffer.Bytes(), Command: "bash", } if shellType == common.LoginShell { script.Arguments = []string{"--login"} } return &script, nil }
func (b *CmdShell) GenerateScript(build *common.Build, shellType common.ShellType) (*common.ShellScript, error) { var buffer bytes.Buffer w := bufio.NewWriter(&buffer) projectDir := build.FullProjectDir() projectDir = helpers.ToBackslash(projectDir) b.writeCommand(w, "@echo off") b.writeCommand(w, "echo.") b.writeCommand(w, "setlocal enableextensions") if len(build.Hostname) != 0 { b.writeCommand(w, "echo Running on %s via %s...", "%COMPUTERNAME%", helpers.ShellEscape(build.Hostname)) } else { b.writeCommand(w, "echo Running on %s...", "%COMPUTERNAME%") } if build.AllowGitFetch { b.writeFetchCmd(w, build, projectDir) } else { b.writeCloneCmd(w, build, projectDir) } b.writeCheckoutCmd(w, build) for _, command := range strings.Split(build.Commands, "\n") { command = strings.TrimRight(command, " \t\r\n") if strings.TrimSpace(command) == "" { b.writeCommand(w, "echo.") continue } if !helpers.BoolOrDefault(build.Runner.DisableVerbose, false) { b.writeCommand(w, "echo %s", command) } b.writeCommandChecked(w, "%s", command) } w.Flush() env := []string{ fmt.Sprintf("CI_BUILD_REF=%s", build.Sha), fmt.Sprintf("CI_BUILD_BEFORE_SHA=%s", build.BeforeSha), fmt.Sprintf("CI_BUILD_REF_NAME=%s", build.RefName), fmt.Sprintf("CI_BUILD_ID=%d", build.ID), fmt.Sprintf("CI_BUILD_REPO=%s", build.RepoURL), fmt.Sprintf("CI_PROJECT_ID=%d", build.ProjectID), fmt.Sprintf("CI_PROJECT_DIR=%s", projectDir), "CI=true", "CI_SERVER=yes", "CI_SERVER_NAME=GitLab CI", "CI_SERVER_VERSION=", "CI_SERVER_REVISION=", "GITLAB_CI=true", } script := common.ShellScript{ Environment: env, Script: buffer.Bytes(), Command: "cmd", Arguments: []string{"/Q", "/C"}, PassFile: true, Extension: "cmd", } return &script, nil }
func runSingle(c *cli.Context) { buildsDir := c.String("builds-dir") shell := c.String("shell") config := common.NewConfig() runner := common.RunnerConfig{ URL: c.String("url"), Token: c.String("token"), Executor: c.String("executor"), BuildsDir: &buildsDir, Shell: &shell, } if len(runner.URL) == 0 { log.Fatalln("Missing URL") } if len(runner.Token) == 0 { log.Fatalln("Missing Token") } if len(runner.Executor) == 0 { log.Fatalln("Missing Executor") } go runServer(c.String("addr")) go runHerokuURL(c.String("heroku-url")) signals := make(chan os.Signal) signal.Notify(signals, os.Interrupt, syscall.SIGTERM) log.Println("Starting runner for", runner.URL, "with token", runner.ShortDescription(), "...") finished := false abortSignal := make(chan os.Signal) doneSignal := make(chan int, 1) go func() { interrupt := <-signals log.Warningln("Requested exit:", interrupt) finished = true go func() { for { abortSignal <- interrupt } }() select { case newSignal := <-signals: log.Fatalln("forced exit:", newSignal) case <-time.After(common.ShutdownTimeout * time.Second): log.Fatalln("shutdown timedout") case <-doneSignal: } }() for !finished { buildData, healthy := common.GetBuild(runner) if !healthy { log.Println("Runner is not healthy!") select { case <-time.After(common.NotHealthyCheckInterval * time.Second): case <-abortSignal: } continue } if buildData == nil { select { case <-time.After(common.CheckInterval * time.Second): case <-abortSignal: } continue } newBuild := common.Build{ GetBuildResponse: *buildData, Runner: &runner, BuildAbort: abortSignal, } newBuild.AssignID() newBuild.Run(config) } doneSignal <- 0 }
func (r *RunSingleCommand) Execute(c *cli.Context) { if len(r.URL) == 0 { log.Fatalln("Missing URL") } if len(r.Token) == 0 { log.Fatalln("Missing Token") } if len(r.Executor) == 0 { log.Fatalln("Missing Executor") } config := common.NewConfig() signals := make(chan os.Signal) signal.Notify(signals, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) log.Println("Starting runner for", r.URL, "with token", r.ShortDescription(), "...") finished := false abortSignal := make(chan os.Signal) doneSignal := make(chan int, 1) go func() { interrupt := <-signals finished = true // request stop, but wait for force exit for interrupt == syscall.SIGQUIT { log.Warningln("Requested quit, waiting for builds to finish") interrupt = <-signals } log.Warningln("Requested exit:", interrupt) go func() { for { abortSignal <- interrupt } }() select { case newSignal := <-signals: log.Fatalln("forced exit:", newSignal) case <-time.After(common.ShutdownTimeout * time.Second): log.Fatalln("shutdown timedout") case <-doneSignal: } }() for !finished { buildData, healthy := common.GetBuild(r.RunnerConfig) if !healthy { log.Println("Runner is not healthy!") select { case <-time.After(common.NotHealthyCheckInterval * time.Second): case <-abortSignal: } continue } if buildData == nil { select { case <-time.After(common.CheckInterval * time.Second): case <-abortSignal: } continue } newBuild := common.Build{ GetBuildResponse: *buildData, Runner: &r.RunnerConfig, BuildAbort: abortSignal, } newBuild.AssignID() newBuild.Run(config) } doneSignal <- 0 }