// DownloadStep ... func DownloadStep(collectionURI string, collection models.StepCollectionModel, id, version, commithash string) error { downloadLocations, err := collection.GetDownloadLocations(id, version) if err != nil { return err } route, found := ReadRoute(collectionURI) if !found { return fmt.Errorf("No routing found for lib: %s", collectionURI) } stepPth := GetStepCacheDirPath(route, id, version) if exist, err := pathutil.IsPathExists(stepPth); err != nil { return err } else if exist { return nil } success := false for _, downloadLocation := range downloadLocations { switch downloadLocation.Type { case "zip": err := retry.Times(2).Wait(3 * time.Second).Try(func(attempt uint) error { return cmdex.DownloadAndUnZIP(downloadLocation.Src, stepPth) }) if err != nil { log.Warn("Failed to download step.zip: ", err) } else { success = true return nil } case "git": err := retry.Times(2).Wait(3 * time.Second).Try(func(attempt uint) error { return cmdex.GitCloneTagOrBranchAndValidateCommitHash(downloadLocation.Src, stepPth, version, commithash) }) if err != nil { log.Warnf("Failed to clone step (%s): %v", downloadLocation.Src, err) } else { success = true return nil } default: return fmt.Errorf("Failed to download: Invalid download location (%#v) for step %#v (%#v)", downloadLocation, id, version) } } if !success { return errors.New("Failed to download step") } return nil }
func auditStepModelBeforeSharePullRequest(step models.StepModel, stepID, version string) error { if err := step.Audit(); err != nil { return fmt.Errorf("Failed to audit step infos, error: %s", err) } pth, err := pathutil.NormalizedOSTempDirPath(stepID + version) if err != nil { return fmt.Errorf("Failed to create a temporary directory for the step's audit, error: %s", err) } if step.Source == nil { return fmt.Errorf("Missing Source porperty") } err = retry.Times(2).Wait(3 * time.Second).Try(func(attempt uint) error { return cmdex.GitCloneTag(step.Source.Git, pth, version) }) if err != nil { return fmt.Errorf("Failed to git-clone the step (url: %s) version (%s), error: %s", step.Source.Git, version, err) } latestCommit, err := cmdex.GitGetLatestCommitHashOnHead(pth) if err != nil { return fmt.Errorf("Failed to get git-latest-commit-hash, error: %s", err) } if latestCommit != step.Source.Commit { return fmt.Errorf("Step commit hash (%s) should be the latest commit hash (%s) on git tag", step.Source.Commit, latestCommit) } return nil }
// Install ... func (toolkit GoToolkit) Install() error { versionStr := minGoVersionForToolkit osStr := runtime.GOOS archStr := runtime.GOARCH extentionStr := "tar.gz" if osStr == "windows" { extentionStr = "zip" } downloadURL := fmt.Sprintf("https://storage.googleapis.com/golang/go%s.%s-%s.%s", versionStr, osStr, archStr, extentionStr) log.Debugln("downloadURL: ", downloadURL) goTmpDirPath := goToolkitTmpDirPath() if err := pathutil.EnsureDirExist(goTmpDirPath); err != nil { return fmt.Errorf("Failed to create Toolkits TMP directory, error: %s", err) } localFileName := "go." + extentionStr goArchiveDownloadPath := filepath.Join(goTmpDirPath, localFileName) var downloadErr error fmt.Print("=> Downloading ...") progress.SimpleProgress(".", 2*time.Second, func() { downloadErr = retry.Times(2).Wait(5 * time.Second).Try(func(attempt uint) error { if attempt > 0 { fmt.Println() fmt.Println("==> Download failed, retrying ...") fmt.Println() } return tools.DownloadFile(downloadURL, goArchiveDownloadPath) }) }) if downloadErr != nil { return fmt.Errorf("Failed to download toolkit (%s), error: %s", downloadURL, downloadErr) } log.Debugln("Toolkit downloaded to: ", goArchiveDownloadPath) fmt.Println("=> Installing ...") if err := installGoTar(goArchiveDownloadPath); err != nil { return fmt.Errorf("Failed to install Go toolkit, error: %s", err) } if err := os.Remove(goArchiveDownloadPath); err != nil { return fmt.Errorf("Failed to remove the downloaded Go archive (path: %s), error: %s", goArchiveDownloadPath, err) } fmt.Println("=> Installing [DONE]") return nil }
func updateCollection(steplibSource string) (models.StepCollectionModel, error) { route, found := stepman.ReadRoute(steplibSource) if !found { log.Warnf("No route found for collection: %s, cleaning up routing..", steplibSource) if err := stepman.CleanupDanglingLib(steplibSource); err != nil { log.Errorf("Error cleaning up lib: %s", steplibSource) } log.Infof("Call 'stepman setup -c %s' for a clean setup", steplibSource) return models.StepCollectionModel{}, fmt.Errorf("No route found for StepLib: %s", steplibSource) } isLocalSteplib := strings.HasPrefix(steplibSource, "file://") if isLocalSteplib { if err := stepman.CleanupRoute(route); err != nil { return models.StepCollectionModel{}, fmt.Errorf("Failed to cleanup route for StepLib: %s", steplibSource) } if err := setupSteplib(steplibSource, false); err != nil { return models.StepCollectionModel{}, fmt.Errorf("Failed to setup StepLib: %s", steplibSource) } } else { pth := stepman.GetCollectionBaseDirPath(route) if exists, err := pathutil.IsPathExists(pth); err != nil { return models.StepCollectionModel{}, err } else if !exists { return models.StepCollectionModel{}, errors.New("Not initialized") } gitPullErr := retry.Times(2).Wait(3 * time.Second).Try(func(attempt uint) error { if attempt > 0 { log.Infoln("Retrying ...") } return cmdex.GitPull(pth) }) if gitPullErr != nil { return models.StepCollectionModel{}, fmt.Errorf("Failed to update StepLib git repository, error: %s", gitPullErr) } if err := stepman.ReGenerateStepSpec(route); err != nil { return models.StepCollectionModel{}, err } } return stepman.ReadStepSpec(steplibSource) }
func findDeployPth(deployDir, baseName, ext string) (string, error) { deployPth := "" retryApkName := baseName + ext err := retry.Times(10).Wait(1 * time.Second).Try(func(attempt uint) error { if attempt > 0 { log.Warn(" Retrying...") } pth, pathErr := createDeployPth(deployDir, retryApkName) if pathErr != nil { log.Warn(" %d attempt failed:", attempt+1) log.Detail(pathErr.Error()) } t := time.Now() retryApkName = baseName + t.Format("20060102150405") + ext deployPth = pth return pathErr }) return deployPth, err }
// CheckIsPluginInstalled ... func CheckIsPluginInstalled(name string, dependency PluginDependency) error { _, found, err := plugins.LoadPlugin(name) if err != nil { return err } currentVersion := "" installOrUpdate := false if !found { fmt.Println() log.Warnf("Default plugin (%s) NOT found.", name) fmt.Println() fmt.Print("Installing...") installOrUpdate = true currentVersion = dependency.MinVersion } else { installedVersion, err := plugins.GetPluginVersion(name) if err != nil { return err } if installedVersion == nil { fmt.Println() log.Warnf("Default plugin (%s) is not installed from git, no version info available.", name) fmt.Println() currentVersion = "local" } else { currentVersion = installedVersion.String() minVersion, err := ver.NewVersion(dependency.MinVersion) if err != nil { return err } if installedVersion.LessThan(minVersion) { fmt.Println() log.Warnf("Default plugin (%s) version (%s) is lower than required (%s).", name, installedVersion.String(), minVersion.String()) fmt.Println() log.Infoln("Updating...") installOrUpdate = true currentVersion = dependency.MinVersion } } } if installOrUpdate { var plugin plugins.Plugin err := progress.SimpleProgressE(".", 2*time.Second, func() error { return retry.Times(2).Wait(5 * time.Second).Try(func(attempt uint) error { if attempt > 0 { fmt.Println() fmt.Print("==> Download failed, retrying ...") } p, _, err := plugins.InstallPlugin(dependency.Source, dependency.Binary, dependency.MinVersion) plugin = p return err }) }) fmt.Println() if err != nil { return fmt.Errorf("Failed to install plugin, error: %s", err) } if len(plugin.Description) > 0 { fmt.Println() fmt.Println(plugin.Description) fmt.Println() } } pluginDir := plugins.GetPluginDir(name) log.Infof(" * %s Plugin (%s) : %s", colorstring.Green("[OK]"), name, pluginDir) log.Infof(" version : %s", currentVersion) return nil }
func checkIsBitriseToolInstalled(toolname, minVersion string, isInstall bool) error { doInstall := func() error { officialGithub := "https://github.com/bitrise-io/" + toolname fmt.Println() log.Warnln("No supported " + toolname + " version found.") log.Infoln("You can find more information about "+toolname+" on its official GitHub page:", officialGithub) // Install fmt.Print("Installing...") err := progress.SimpleProgressE(".", 2*time.Second, func() error { return retry.Times(2).Wait(5 * time.Second).Try(func(attempt uint) error { if attempt > 0 { fmt.Println() fmt.Print("==> Download failed, retrying ...") } return tools.InstallToolFromGitHub(toolname, "bitrise-io", minVersion) }) }) fmt.Println() if err != nil { return err } // check again return checkIsBitriseToolInstalled(toolname, minVersion, false) } // check whether installed progInstallPth, err := utils.CheckProgramInstalledPath(toolname) if err != nil { if !isInstall { return err } return doInstall() } verStr, err := cmdex.RunCommandAndReturnStdout(toolname, "-version") if err != nil { log.Infoln("") return errors.New("Failed to get version") } // version check isVersionOk, err := versions.IsVersionGreaterOrEqual(verStr, minVersion) if err != nil { log.Error("Failed to validate installed version") return err } if !isVersionOk { log.Warn("Installed "+toolname+" found, but not a supported version: ", verStr) if !isInstall { return errors.New("Failed to install required version.") } log.Warn("Updating...") return doInstall() } log.Infoln(" * "+colorstring.Green("[OK]")+" "+toolname+" :", progInstallPth) log.Infoln(" version :", verStr) return nil }
func main() { configs := createConfigsModelFromEnvs() fmt.Println() configs.print() if err := configs.validate(); err != nil { log.Error("Issue with input: %s", err) os.Exit(1) } nugetPth := "/Library/Frameworks/Mono.framework/Versions/Current/bin/nuget" nugetRestoreCmdArgs := []string{nugetPth} if configs.NugetVersion == "latest" { fmt.Println() log.Info("Updating Nuget to latest version...") // "sudo $nuget update -self" cmdArgs := []string{"sudo", nugetPth, "update", "-self"} cmd, err := cmdex.NewCommandFromSlice(cmdArgs) if err != nil { log.Error("Failed to create command from args (%v), error: %s", cmdArgs, err) os.Exit(1) } cmd.SetStdout(os.Stdout) cmd.SetStderr(os.Stderr) log.Done("$ %s", cmdex.PrintableCommandArgs(false, cmdArgs)) if err := cmd.Run(); err != nil { log.Error("Failed to update nuget, error: %s", err) os.Exit(1) } } else if configs.NugetVersion != "" { fmt.Println() log.Info("Downloading Nuget %s version...", configs.NugetVersion) tmpDir, err := pathutil.NormalizedOSTempDirPath("__nuget__") if err != nil { log.Error("Failed to create tmp dir, error: %s", err) os.Exit(1) } downloadPth := filepath.Join(tmpDir, "nuget.exe") // https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe nugetURL := fmt.Sprintf("https://dist.nuget.org/win-x86-commandline/v%s/nuget.exe", configs.NugetVersion) log.Detail("Download URL: %s", nugetURL) if err := DownloadFile(nugetURL, downloadPth); err != nil { log.Warn("Download failed, error: %s", err) // https://dist.nuget.org/win-x86-commandline/v3.4.4/NuGet.exe nugetURL = fmt.Sprintf("https://dist.nuget.org/win-x86-commandline/v%s/NuGet.exe", configs.NugetVersion) log.Detail("Retry download URl: %s", nugetURL) if err := DownloadFile(nugetURL, downloadPth); err != nil { log.Error("Failed to download nuget, error: %s", err) os.Exit(1) } } nugetRestoreCmdArgs = []string{constants.MonoPath, downloadPth} } fmt.Println() log.Info("Restoring Nuget packages...") nugetRestoreCmdArgs = append(nugetRestoreCmdArgs, "restore", configs.XamarinSolution) if err := retry.Times(1).Try(func(attempt uint) error { if attempt > 0 { log.Warn("Attempt %d failed, retrying...", attempt) } log.Done("$ %s", cmdex.PrintableCommandArgs(false, nugetRestoreCmdArgs)) cmd, err := cmdex.NewCommandFromSlice(nugetRestoreCmdArgs) if err != nil { log.Error("Failed to create Nuget command, error: %s", err) os.Exit(1) } cmd.SetStdout(os.Stdout) cmd.SetStderr(os.Stderr) if err := cmd.Run(); err != nil { log.Error("Restore failed, error: %s", err) return err } return nil }); err != nil { log.Error("Nuget restore failed, error: %s", err) os.Exit(1) } }
func runStep(step stepmanModels.StepModel, stepIDData models.StepIDData, stepDir string, environments []envmanModels.EnvironmentItemModel, buildRunResults models.BuildRunResultsModel) (int, []envmanModels.EnvironmentItemModel, error) { log.Debugf("[BITRISE_CLI] - Try running step: %s (%s)", stepIDData.IDorURI, stepIDData.Version) // Check & Install Step Dependencies // [!] Make sure this happens BEFORE the Toolkit Bootstrap, // so that if a Toolkit requires/allows the use of additional dependencies // required for the step (e.g. a brew installed OpenSSH) it can be done // with a Toolkit+Deps if err := retry.Times(2).Try(func(attempt uint) error { if attempt > 0 { fmt.Println() log.Warn("Installing Step dependency failed, retrying ...") } return checkAndInstallStepDependencies(step) }); err != nil { return 1, []envmanModels.EnvironmentItemModel{}, fmt.Errorf("Failed to install Step dependency, error: %s", err) } // Collect step inputs if err := tools.EnvmanInitAtPath(configs.InputEnvstorePath); err != nil { return 1, []envmanModels.EnvironmentItemModel{}, fmt.Errorf("Failed to init envman for the Step, error: %s", err) } if err := bitrise.ExportEnvironmentsList(environments); err != nil { return 1, []envmanModels.EnvironmentItemModel{}, fmt.Errorf("Failed to export environment list for the Step, error: %s", err) } evaluatedInputs := []envmanModels.EnvironmentItemModel{} for _, input := range step.Inputs { key, value, err := input.GetKeyValuePair() if err != nil { return 1, []envmanModels.EnvironmentItemModel{}, err } options, err := input.GetOptions() if err != nil { return 1, []envmanModels.EnvironmentItemModel{}, err } if options.IsTemplate != nil && *options.IsTemplate { outStr, err := tools.EnvmanJSONPrint(configs.InputEnvstorePath) if err != nil { return 1, []envmanModels.EnvironmentItemModel{}, fmt.Errorf("EnvmanJSONPrint failed, err: %s", err) } envList, err := envmanModels.NewEnvJSONList(outStr) if err != nil { return 1, []envmanModels.EnvironmentItemModel{}, fmt.Errorf("CreateFromJSON failed, err: %s", err) } evaluatedValue, err := bitrise.EvaluateTemplateToString(value, configs.IsCIMode, configs.IsPullRequestMode, buildRunResults, envList) if err != nil { return 1, []envmanModels.EnvironmentItemModel{}, err } input[key] = evaluatedValue } evaluatedInputs = append(evaluatedInputs, input) } environments = append(environments, evaluatedInputs...) if err := tools.EnvmanInitAtPath(configs.InputEnvstorePath); err != nil { return 1, []envmanModels.EnvironmentItemModel{}, err } if err := bitrise.ExportEnvironmentsList(environments); err != nil { return 1, []envmanModels.EnvironmentItemModel{}, err } // Run step bitriseSourceDir, err := getCurrentBitriseSourceDir(environments) if err != nil { return 1, []envmanModels.EnvironmentItemModel{}, err } if bitriseSourceDir == "" { bitriseSourceDir = configs.CurrentDir } if exit, err := executeStep(step, stepIDData, stepDir, bitriseSourceDir); err != nil { stepOutputs, envErr := bitrise.CollectEnvironmentsFromFile(configs.OutputEnvstorePath) if envErr != nil { return 1, []envmanModels.EnvironmentItemModel{}, envErr } return exit, stepOutputs, err } stepOutputs, err := bitrise.CollectEnvironmentsFromFile(configs.OutputEnvstorePath) if err != nil { return 1, []envmanModels.EnvironmentItemModel{}, err } log.Debugf("[BITRISE_CLI] - Step executed: %s (%s)", stepIDData.IDorURI, stepIDData.Version) return 0, stepOutputs, nil }