func (b *BashShell) generateCommands(info common.ShellScriptInfo) string { var buffer bytes.Buffer w := bufio.NewWriter(&buffer) b.writeExports(w, info) b.writeCdBuildDir(w, info) commands := info.Build.Commands commands = strings.TrimSpace(commands) for _, command := range strings.Split(commands, "\n") { command = strings.TrimSpace(command) if !helpers.BoolOrDefault(info.Build.Runner.DisableVerbose, false) { if command != "" { b.echoColored(w, "$ "+command) } else { b.executeCommand(w, "echo") } } io.WriteString(w, command+"\n") } w.Flush() return b.finalize(buffer.String()) }
func (s *DockerExecutor) createVolumes() ([]string, []string, error) { var binds, volumesFrom []string for _, volume := range s.Config.Docker.Volumes { s.addVolume(&binds, &volumesFrom, volume) } // Cache Git sources: // take path of the projects directory, // because we use `rm -rf` which could remove the mounted volume parentDir := filepath.Dir(s.Build.FullProjectDir()) // Caching is supported only for absolute and non-root paths if filepath.IsAbs(parentDir) && parentDir != "/" { if s.Build.AllowGitFetch && !helpers.BoolOrDefault(s.Config.Docker.DisableCache, false) { // create persistent cache container s.addVolume(&binds, &volumesFrom, parentDir) } else { // create temporary cache container container, _ := s.createCacheVolume("", parentDir) if container != nil { s.caches = append(s.caches, container) volumesFrom = append(volumesFrom, container.ID) } } } return binds, volumesFrom, nil }
func (s *ParallelsExecutor) Cleanup() { s.sshCommand.Cleanup() if s.vmName != "" { prl.Kill(s.vmName) if helpers.BoolOrDefault(s.Config.Parallels.DisableSnapshots, false) || !s.provisioned { prl.Delete(s.vmName) } } s.AbstractExecutor.Cleanup() }
func (b *PowerShell) GenerateScript(info common.ShellScriptInfo) (*common.ShellScript, error) { var buffer bytes.Buffer w := bufio.NewWriter(&buffer) build := info.Build 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\"", strings.Replace(command, "\"", "`\"", -1)) } b.writeCommandChecked(w, "%s", command) } w.Flush() script := common.ShellScript{ Environment: b.GetVariables(build, projectDir, info.Environment), BuildScript: buffer.String(), Command: "powershell", Arguments: []string{"-noprofile", "-noninteractive", "-executionpolicy", "Bypass", "-command"}, PassFile: true, Extension: "ps1", } return &script, nil }
func (b *CmdShell) GenerateScript(info common.ShellScriptInfo) (*common.ShellScript, error) { var buffer bytes.Buffer w := bufio.NewWriter(&buffer) build := info.Build 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() script := common.ShellScript{ Environment: b.GetVariables(build, projectDir, info.Environment), Script: buffer.String(), Command: "cmd", Arguments: []string{"/Q", "/C"}, PassFile: true, Extension: "cmd", } return &script, nil }
func (s *DockerExecutor) addCacheVolume(binds, volumesFrom *[]string, containerPath string) error { var err error containerPath = s.getAbsoluteContainerPath(containerPath) // disable cache for automatic container cache, but leave it for host volumes (they are shared on purpose) if helpers.BoolOrDefault(s.Config.Docker.DisableCache, false) { s.Debugln("Container cache for", containerPath, " is disabled.") return nil } hash := md5.Sum([]byte(containerPath)) // use host-based cache if cacheDir := helpers.StringOrDefault(s.Config.Docker.CacheDir, ""); cacheDir != "" { hostPath := fmt.Sprintf("%s/%s/%x", cacheDir, s.Build.ProjectUniqueName(), hash) hostPath, err := filepath.Abs(hostPath) if err != nil { return err } s.Debugln("Using path", hostPath, "as cache for", containerPath, "...") *binds = append(*binds, fmt.Sprintf("%v:%v", hostPath, containerPath)) return nil } // get existing cache container containerName := fmt.Sprintf("%s-cache-%x", s.Build.ProjectUniqueName(), hash) container, _ := s.client.InspectContainer(containerName) // check if we have valid cache, if not remove the broken container if container != nil && container.Volumes[containerPath] == "" { s.removeContainer(container.ID) container = nil } // create new cache container for that project if container == nil { container, err = s.createCacheVolume(containerName, containerPath) if err != nil { return err } } s.Debugln("Using container", container.ID, "as cache", containerPath, "...") *volumesFrom = append(*volumesFrom, container.ID) return nil }
func (s *ParallelsExecutor) Prepare(globalConfig *common.Config, config *common.RunnerConfig, build *common.Build) error { err := s.AbstractExecutor.Prepare(globalConfig, config, build) if err != nil { return err } if s.ShellScript.PassFile { return errors.New("Parallels doesn't support shells that require script file") } if s.Config.SSH == nil { return errors.New("Missing SSH configuration") } if s.Config.Parallels == nil { return errors.New("Missing Parallels configuration") } if s.Config.Parallels.BaseName == "" { return errors.New("Missing BaseName setting from Parallels config") } version, err := prl.Version() if err != nil { return err } s.Println("Using Parallels", version, "executor...") // remove invalid VM (removed?) vmStatus, _ := prl.Status(s.vmName) if vmStatus == prl.Invalid { prl.Unregister(s.vmName) } if helpers.BoolOrDefault(s.Config.Parallels.DisableSnapshots, false) { s.vmName = s.Config.Parallels.BaseName + "-" + s.Build.ProjectUniqueName() if prl.Exist(s.vmName) { s.Debugln("Deleting old VM...") prl.Stop(s.vmName) prl.Delete(s.vmName) prl.Unregister(s.vmName) } } else { s.vmName = fmt.Sprintf("%s-runner-%s-concurrent-%d", s.Config.Parallels.BaseName, s.Build.Runner.ShortDescription(), s.Build.RunnerID) } if prl.Exist(s.vmName) { s.Println("Restoring VM from snapshot...") err := s.restoreFromSnapshot() if err != nil { s.Println("Previous VM failed. Deleting, because", err) prl.Stop(s.vmName) prl.Delete(s.vmName) prl.Unregister(s.vmName) } } if !prl.Exist(s.vmName) { s.Println("Creating new VM...") err := s.createVM() if err != nil { return err } if !helpers.BoolOrDefault(s.Config.Parallels.DisableSnapshots, false) { s.Println("Creating default snapshot...") err = prl.CreateSnapshot(s.vmName, "Started") if err != nil { return err } } } s.Debugln("Checking VM status...") status, err := prl.Status(s.vmName) if err != nil { return err } // Start VM if stopped if status == prl.Stopped || status == prl.Suspended { s.Println("Starting VM...") err := prl.Start(s.vmName) if err != nil { return err } } if status != prl.Running { s.Debugln("Waiting for VM to run...") err = prl.WaitForStatus(s.vmName, prl.Running, 60) if err != nil { return err } } s.Println("Waiting VM to become responsive...") err = s.verifyMachine(s.vmName) if err != nil { return err } s.provisioned = true s.Debugln("Updating VM date...") err = prl.TryExec(s.vmName, 20, "sudo", "ntpdate", "-u", "time.apple.com") if err != nil { return err } return nil }
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 (b *BashShell) GenerateScript(info common.ShellScriptInfo) (*common.ShellScript, error) { var buffer bytes.Buffer w := bufio.NewWriter(&buffer) build := info.Build projectDir := build.FullProjectDir() projectDir = helpers.ToSlash(projectDir) gitDir := filepath.Join(projectDir, ".git") projectScript := helpers.ShellEscape(build.FullProjectDir() + ".sh") io.WriteString(w, "#!/usr/bin/env bash\n") io.WriteString(w, "\n") io.WriteString(w, "set -eo pipefail\n") io.WriteString(w, "\n") if len(build.Hostname) != 0 { io.WriteString(w, fmt.Sprintf("echo Running on $(hostname) via %s...", helpers.ShellEscape(build.Hostname))) } else { io.WriteString(w, "echo Running on $(hostname)...\n") } io.WriteString(w, "\n") io.WriteString(w, "echo\n") // Set env variables from build script for _, keyValue := range b.GetVariables(build, projectDir, info.Environment) { io.WriteString(w, "export "+helpers.ShellEscape(keyValue)+"\n") } io.WriteString(w, "\n") io.WriteString(w, "# save script that is read from to file and execute script file on remote server\n") io.WriteString(w, fmt.Sprintf("mkdir -p %s\n", helpers.ShellEscape(projectDir))) io.WriteString(w, fmt.Sprintf("cat > %s; source %s\n", projectScript, projectScript)) io.WriteString(w, "\n") if build.AllowGitFetch { b.writeFetchCmd(w, build, helpers.ShellEscape(projectDir), helpers.ShellEscape(gitDir)) } else { b.writeCloneCmd(w, build, helpers.ShellEscape(projectDir)) } b.writeCheckoutCmd(w, build) io.WriteString(w, "\n") io.WriteString(w, "echo\n") io.WriteString(w, "\n") commands := build.Commands commands = strings.TrimSpace(commands) for _, command := range strings.Split(commands, "\n") { command = strings.TrimSpace(command) if !helpers.BoolOrDefault(build.Runner.DisableVerbose, false) { if command != "" { b.echoColored(w, "$ "+command) } else { io.WriteString(w, "echo\n") } } io.WriteString(w, command+"\n") } io.WriteString(w, "\n") w.Flush() script := common.ShellScript{ Script: buffer.String(), Environment: b.GetVariables(build, projectDir, info.Environment), } // su if info.User != nil { script.Command = "su" if info.Type == common.LoginShell { script.Arguments = []string{"--shell", "/bin/bash", "--login", *info.User} } else { script.Arguments = []string{"--shell", "/bin/bash", *info.User} } } else { script.Command = "bash" if info.Type == common.LoginShell { script.Arguments = []string{"--login"} } } return &script, nil }