Beispiel #1
0
func printFinishShare() {
	fmt.Println()
	log.Info(" * " + colorstring.Green("[OK] ") + "Yeah!! You rock!!")
	fmt.Println()
	fmt.Println("   " + GuideTextForFinish())
	fmt.Println()
	msg := `   You can create a pull request in your forked StepLib repository,
   if you used the main StepLib repository then your repository's url looks like: ` + `
   ` + colorstring.Green("https://github.com/[your-username]/bitrise-steplib") + `

   On GitHub you can find a ` + colorstring.Green("'Compare & pull request'") + ` button, in the ` + colorstring.Green("'Your recently pushed branches:'") + ` section,
   which will bring you to the 'Open a pull request' page, where you can review and create your Pull Request.
	`
	fmt.Println(msg)
}
Beispiel #2
0
// InstallWithAptGetIfNeeded ...
func InstallWithAptGetIfNeeded(tool string, isCIMode bool) error {
	if out, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("which", tool); err != nil {
		if err.Error() == "exit status 1" && out == "" {
			// Tool isn't installed -- install it...
			if !isCIMode {
				log.Infof("This step requires %s, which is not installed", tool)
				allow, err := goinp.AskForBool("Would you like to install (" + tool + ") with brew ? [yes/no]")
				if err != nil {
					return err
				}
				if !allow {
					return errors.New("(" + tool + ") is required for step")
				}
			}

			log.Infof("(%s) isn't installed, installing...", tool)
			if out, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("sudo", "apt-get", "-y", "install", tool); err != nil {
				log.Errorf("sudo apt-get -y install %s failed -- out: (%s) err: (%s)", tool, out, err)
				return err
			}

			log.Infof(" * "+colorstring.Green("[OK]")+" %s installed", tool)
		} else {
			// which failed
			log.Errorf("which (%s) failed -- out: (%s) err: (%s)", tool, out, err)
			return err
		}
	} else if out != "" {
		// already installed
	} else {
		log.Warnf("which (%s) -- out (%s)", tool, out)
	}

	return nil
}
Beispiel #3
0
func pluginList(c *cli.Context) {
	pluginMap, err := plugins.ListPlugins()
	if err != nil {
		log.Fatalf("Failed to list plugins, err: %s", err)
	}

	pluginNames := []string{}
	for _, plugins := range pluginMap {
		for _, plugin := range plugins {
			pluginNames = append(pluginNames, plugin.PrintableName())
		}
	}
	sort.Strings(pluginNames)

	if len(pluginNames) > 0 {
		fmt.Println("")
		for _, name := range pluginNames {
			fmt.Printf(" ⚡️ %s\n", colorstring.Green(name))
		}
		fmt.Println("")
	} else {
		fmt.Println("")
		fmt.Println("No installed plugin found")
		fmt.Println("")
	}
}
Beispiel #4
0
func doSetupToolkits() error {
	log.Infoln("Checking Bitrise Toolkits...")

	coreToolkits := toolkits.AllSupportedToolkits()

	for _, aCoreTK := range coreToolkits {
		toolkitName := aCoreTK.ToolkitName()
		isInstallRequired, checkResult, err := aCoreTK.Check()
		if err != nil {
			return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
		}

		if isInstallRequired {
			log.Infoln("No installed/suitable '" + toolkitName + "' found, installing toolkit ...")
			if err := aCoreTK.Install(); err != nil {
				return fmt.Errorf("Failed to install toolkit (%s), error: %s", toolkitName, err)
			}

			isInstallRequired, checkResult, err = aCoreTK.Check()
			if err != nil {
				return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
			}
		}
		if isInstallRequired {
			return fmt.Errorf("Toolkit (%s) still reports that it isn't (properly) installed", toolkitName)
		}

		log.Infoln(" * "+colorstring.Green("[OK]")+" "+toolkitName+" :", checkResult.Path)
		log.Infoln("        version :", checkResult.Version)
	}

	return nil
}
Beispiel #5
0
func printFinishCreate(share ShareModel, stepDirInSteplib string, toolMode bool) {
	fmt.Println()
	log.Infof(" * "+colorstring.Green("[OK]")+" Your Step (%s) (%s) added to local StepLib (%s).", share.StepID, share.StepTag, stepDirInSteplib)
	log.Infoln(" *      You can find your Step's step.yml at: " + colorstring.Greenf("%s/step.yml", stepDirInSteplib))
	fmt.Println()
	fmt.Println("   " + GuideTextForShareFinish(toolMode))
}
Beispiel #6
0
func checkIsBitriseToolInstalled(toolname, minVersion string, isInstall bool) error {
	doInstall := func() error {
		installCmdLines := []string{
			"curl -fL https://github.com/bitrise-io/" + toolname + "/releases/download/" + minVersion + "/" + toolname + "-$(uname -s)-$(uname -m) > /usr/local/bin/" + toolname,
			"chmod +x /usr/local/bin/" + toolname,
		}
		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 it's official GitHub page:", officialGithub)
		fmt.Println()

		// Install
		log.Infoln("Installing...")
		fmt.Println(strings.Join(installCmdLines, "\n"))
		if err := cmdex.RunBashCommandLines(installCmdLines); err != nil {
			return err
		}

		// check again
		return checkIsBitriseToolInstalled(toolname, minVersion, false)
	}

	// check whether installed
	progInstallPth, err := 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
}
Beispiel #7
0
// GuideTextForStart ...
func GuideTextForStart() string {
	guide := colorstring.Blue("Fork the StepLib repository") + " you want to share your Step in.\n" +
		`   You can find the main ("official") StepLib repository at: ` + colorstring.Green("https://github.com/bitrise-io/bitrise-steplib") + `

   ` + colorstring.Yellow("Note") + `: You can use any StepLib repository you like,
     the StepLib system is decentralized, you don't have to work with the main StepLib repository
     if you don't want to. Feel free to maintain and use your own (or your team's) Step Library.
`
	return guide
}
Beispiel #8
0
// InstallWithAptGetIfNeeded ...
func InstallWithAptGetIfNeeded(aptGetDep stepmanModels.AptGetDepModel, isCIMode bool) error {
	isDepInstalled := false
	// First do a "which", to see if the binary is available.
	// Can be available from another source, not just from brew,
	// e.g. it's common to use NVM or similar to install and manage the Node.js version.
	{
		if out, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("which", aptGetDep.GetBinaryName()); err != nil {
			if err.Error() == "exit status 1" && out == "" {
				isDepInstalled = false
			} else {
				// unexpected `which` error
				return fmt.Errorf("which (%s) failed -- out: (%s) err: (%s)", aptGetDep.Name, out, err)
			}
		} else if out != "" {
			isDepInstalled = true
		} else {
			// no error but which's output was empty
			return fmt.Errorf("which (%s) failed -- no error (exit code 0) but output was empty", aptGetDep.Name)
		}
	}

	// then do a package manager specific lookup
	{
		if !isDepInstalled {
			// which did not find the binary, also check in brew,
			// whether the package is installed
			isDepInstalled = checkIfAptPackageInstalled(aptGetDep.Name)
		}
	}

	if !isDepInstalled {
		// Tool isn't installed -- install it...
		if !isCIMode {
			log.Infof(`This step requires "%s" to be available, but it is not installed.`, aptGetDep.GetBinaryName())
			allow, err := goinp.AskForBoolWithDefault(`Would you like to install the "`+aptGetDep.Name+`" package with apt-get?`, true)
			if err != nil {
				return err
			}
			if !allow {
				return errors.New("(" + aptGetDep.Name + ") is required for step")
			}
		}

		log.Infof("(%s) isn't installed, installing...", aptGetDep.Name)
		if cmdOut, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("sudo", "apt-get", "-y", "install", aptGetDep.Name); err != nil {
			log.Errorf("sudo apt-get -y install %s failed -- out: (%s) err: (%s)", aptGetDep.Name, cmdOut, err)
			return err
		}

		log.Infof(" * "+colorstring.Green("[OK]")+" %s installed", aptGetDep.Name)
	}

	return nil
}
Beispiel #9
0
func share(c *cli.Context) error {
	toolMode := c.Bool(ToolMode)

	guide := `
Do you want to ` + colorstring.Green("share ") + colorstring.Yellow("your ") + colorstring.Magenta("own ") + colorstring.Blue("Step") + ` with the world? Awesome!!
To get started you can find a template Step repository at: ` + colorstring.Green("https://github.com/bitrise-steplib/step-template") + `

Once you have your Step in a ` + colorstring.Yellow("public git repository") + ` you can share it with others.

To share your Step just follow these steps (pun intended ;) :

1. ` + GuideTextForStart() + `
2. ` + GuideTextForShareStart(toolMode) + `
3. ` + GuideTextForShareCreate(toolMode) + `
4. ` + GuideTextForAudit(toolMode) + `
5. ` + GuideTextForShareFinish(toolMode) + `
6. ` + GuideTextForFinish()
	fmt.Println(guide)

	return nil
}
Beispiel #10
0
func printRawEnvInfo(env models.EnvInfoModel) {
	if env.DefaultValue != "" {
		fmt.Printf("- %s: %s\n", colorstring.Green(env.Key), env.DefaultValue)
	} else {
		fmt.Printf("- %s\n", colorstring.Green(env.Key))
	}

	fmt.Printf("  %s: %v\n", colorstring.Green("is expand"), env.IsExpand)

	if len(env.ValueOptions) > 0 {
		fmt.Printf("  %s:\n", colorstring.Green("value options"))
		for _, option := range env.ValueOptions {
			fmt.Printf("  - %s\n", option)
		}
	}

	if env.Description != "" {
		fmt.Printf("  %s:\n", colorstring.Green("description"))
		fmt.Printf("  %s\n", env.Description)
	}
}
Beispiel #11
0
// GuideTextForShareStart ...
func GuideTextForShareStart(toolMode bool) string {
	name := "stepman"
	if toolMode {
		name = "bitrise"
	}

	guide := "Call " + colorstring.Blue("'"+name+" share start -c STEPLIB_REPO_FORK_GIT_URL'") + ", with the " + colorstring.Yellow("git clone url") + " of " + colorstring.Yellow("your forked StepLib repository") + ".\n" +
		`   This will prepare your forked StepLib locally for sharing.

   For example, if you want to share your Step in the main StepLib repository you should call:
     ` + colorstring.Green(""+name+" share start -c https://github.com/[your-username]/bitrise-steplib.git") + `
	`
	return guide
}
Beispiel #12
0
// InstallWithBrewIfNeeded ...
func InstallWithBrewIfNeeded(brewDep stepmanModels.BrewDepModel, isCIMode bool) error {
	isDepInstalled := false
	// First do a "which", to see if the binary is available.
	// Can be available from another source, not just from brew,
	// e.g. it's common to use NVM or similar to install and manage the Node.js version.
	if out, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("which", brewDep.GetBinaryName()); err != nil {
		if err.Error() == "exit status 1" && out == "" {
			isDepInstalled = false
		} else {
			// unexpected `which` error
			return fmt.Errorf("which (%s) failed -- out: (%s) err: (%s)", brewDep.Name, out, err)
		}
	} else if out != "" {
		isDepInstalled = true
	} else {
		// no error but which's output was empty
		return fmt.Errorf("which (%s) failed -- no error (exit code 0) but output was empty", brewDep.Name)
	}

	if !isDepInstalled {
		// which did not find the binary, also check in brew,
		// whether the package is installed
		isDepInstalled = checkIfBrewPackageInstalled(brewDep.Name)
	}

	if !isDepInstalled {
		// Tool isn't installed -- install it...
		if !isCIMode {
			log.Infof("This step requires %s, which is not installed", brewDep.Name)
			allow, err := goinp.AskForBool("Would you like to install (" + brewDep.Name + ") with brew?")
			if err != nil {
				return err
			}
			if !allow {
				return errors.New("(" + brewDep.Name + ") is required for step")
			}
		}

		log.Infof("(%s) isn't installed, installing...", brewDep.Name)
		if out, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("brew", "install", brewDep.Name); err != nil {
			log.Errorf("brew install %s failed -- out: (%s) err: (%s)", brewDep.Name, out, err)
			return err
		}
		log.Infof(" * "+colorstring.Green("[OK]")+" %s installed", brewDep.Name)
	}

	return nil
}
Beispiel #13
0
// GuideTextForShareCreate ...
func GuideTextForShareCreate(toolMode bool) string {
	name := "stepman"
	if toolMode {
		name = "bitrise"
	}

	guide := "Next, call " + colorstring.Blue("'"+name+" share create --tag STEP_VERSION_TAG --git STEP_GIT_URI --stepid STEP_ID'") + `,
   to add your Step to your forked StepLib repository (locally).

   This will copy the required step.yml file from your Step's repository.
   This is all what's required to add your step (or a new version) to a StepLib.

   ` + colorstring.Yellow("Important") + `: You have to add the (version) tag to your Step's repository before you would call this!
     You can do that at: https://github.com/[your-username]/[step-repository]/tags

   An example call:
     ` + colorstring.Green(""+name+" share create --tag 1.0.0 --git https://github.com/[your-username]/[step-repository].git --stepid my-awesome-step") + `

   ` + colorstring.Yellow("Note") + `: You'll still be able to modify the step.yml in the StepLib after this.
	`
	return guide
}
Beispiel #14
0
// PrintInstalledXcodeInfos ...
func PrintInstalledXcodeInfos() error {
	xcodeSelectPth, err := cmdex.RunCommandAndReturnStdout("xcode-select", "--print-path")
	if err != nil {
		xcodeSelectPth = "xcode-select --print-path failed to detect the location of activate Xcode Command Line Tools path"
	}

	progInstallPth, err := utils.CheckProgramInstalledPath("xcodebuild")
	if err != nil {
		return errors.New("xcodebuild is not installed")
	}

	isFullXcodeAvailable := false
	verStr, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("xcodebuild", "-version")
	if err != nil {
		// No full Xcode available, only the Command Line Tools
		// verStr is something like "xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance"
		isFullXcodeAvailable = false
	} else {
		// version OK - full Xcode available
		//  we'll just format it a bit to fit into one line
		isFullXcodeAvailable = true
		verStr = strings.Join(strings.Split(verStr, "\n"), " | ")
	}

	log.Infoln(" * "+colorstring.Green("[OK]")+" xcodebuild path :", progInstallPth)
	if !isFullXcodeAvailable {
		log.Infoln("        version (xcodebuild) :", colorstring.Yellowf("%s", verStr))
	} else {
		log.Infoln("        version (xcodebuild) :", verStr)
	}
	log.Infoln("        active Xcode (Command Line Tools) path (xcode-select --print-path) :", xcodeSelectPth)
	if !isFullXcodeAvailable {
		log.Warn(colorstring.Yellowf("%s", "No Xcode found, only the Xcode Command Line Tools are available!"))
		log.Warn(colorstring.Yellowf("%s", "Full Xcode is required to build, test and archive iOS apps!"))
	}

	return nil
}
Beispiel #15
0
// InstallWithBrewIfNeeded ...
func InstallWithBrewIfNeeded(tool string, isCIMode bool) error {
	if err := checkWithBrewProgramInstalled(tool); err != nil {
		if !isCIMode {
			log.Infof("This step requires %s, which is not installed", tool)
			allow, err := goinp.AskForBool("Would you like to install (" + tool + ") with brew ? [yes/no]")
			if err != nil {
				return err
			}
			if !allow {
				return errors.New("(" + tool + ") is required for step")
			}
		}

		log.Infof("(%s) isn't installed, installing...", tool)
		if out, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("brew", "install", tool); err != nil {
			log.Errorf("brew install %s failed -- out: (%s) err: (%s)", tool, out, err)
			return err
		}
		log.Infof(" * "+colorstring.Green("[OK]")+" %s installed", tool)
		return nil
	}
	return nil
}
Beispiel #16
0
// CheckIsHomebrewInstalled ...
func CheckIsHomebrewInstalled(isFullSetupMode bool) error {
	brewRubyInstallCmdString := `$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
	officialSiteURL := "http://brew.sh/"

	progInstallPth, err := utils.CheckProgramInstalledPath("brew")
	if err != nil {
		fmt.Println()
		log.Warn("It seems that Homebrew is not installed on your system.")
		log.Infoln("Homebrew (short: brew) is required in order to be able to auto-install all the bitrise dependencies.")
		log.Infoln("You should be able to install brew by copying this command and running it in your Terminal:")
		log.Infoln(brewRubyInstallCmdString)
		log.Infoln("You can find more information about Homebrew on its official site at:", officialSiteURL)
		log.Warn("Once the installation of brew is finished you should call the bitrise setup again.")
		return err
	}
	verStr, err := cmdex.RunCommandAndReturnStdout("brew", "--version")
	if err != nil {
		log.Infoln("")
		return errors.New("Failed to get version")
	}

	if isFullSetupMode {
		// brew doctor
		doctorOutput, err := cmdex.RunCommandAndReturnCombinedStdoutAndStderr("brew", "doctor")
		if err != nil {
			fmt.Println("")
			log.Warn("brew doctor returned an error:")
			log.Warnf("%s", doctorOutput)
			return errors.New("Failed to: brew doctor")
		}
	}

	log.Infoln(" * "+colorstring.Green("[OK]")+" Homebrew :", progInstallPth)
	log.Infoln("        version :", verStr)
	return nil
}
Beispiel #17
0
func exportProvisioningProfiles(provProfileFileInfos []provprofile.ProvisioningProfileFileInfoModel,
	exportTargetDirPath string) error {

	for idx, aProvProfileFileInfo := range provProfileFileInfos {
		if idx != 0 {
			fmt.Println()
		}
		provProfileInfo := aProvProfileFileInfo.ProvisioningProfileInfo
		log.Infoln("   "+colorstring.Green("Exporting Provisioning Profile:"), provProfileInfo.Name)
		log.Infoln("                      App ID Name:", provProfileInfo.AppIDName)
		log.Infoln("                           App ID:", provProfileInfo.Entitlements.AppID)
		log.Infoln("                  Expiration Date:", provProfileInfo.ExpirationDate)
		log.Infoln("                             UUID:", provProfileInfo.UUID)
		log.Infoln("                         TeamName:", provProfileInfo.TeamName)
		log.Infoln("                          Team ID:", provProfileInfo.Entitlements.TeamID)
		exportFileName := provProfileExportFileName(aProvProfileFileInfo)
		exportPth := filepath.Join(exportTargetDirPath, exportFileName)
		if err := cmdex.RunCommand("cp", aProvProfileFileInfo.Path, exportPth); err != nil {
			return fmt.Errorf("Failed to copy Provisioning Profile (from: %s) (to: %s), error: %s",
				aProvProfileFileInfo.Path, exportPth, err)
		}
	}
	return nil
}
Beispiel #18
0
// Done ...
func Done(format string, v ...interface{}) {
	message := fmt.Sprintf(format, v...)
	fmt.Println(colorstring.Green(message))
}
Beispiel #19
0
func initConfig(c *cli.Context) error {
	PrintBitriseHeaderASCIIArt(c.App.Version)

	bitriseConfigFileRelPath := "./" + DefaultBitriseConfigFileName
	bitriseSecretsFileRelPath := "./" + DefaultSecretsFileName

	if exists, err := pathutil.IsPathExists(bitriseConfigFileRelPath); err != nil {
		log.Fatalf("Failed to init path (%s), error: %s", bitriseConfigFileRelPath, err)
	} else if exists {
		ask := fmt.Sprintf("A config file already exists at %s - do you want to overwrite it?", bitriseConfigFileRelPath)
		if val, err := goinp.AskForBool(ask); err != nil {
			log.Fatalf("Failed to ask for input, error: %s", err)
		} else if !val {
			log.Info("Init canceled, existing file won't be overwritten.")
			os.Exit(0)
		}
	}

	userInputProjectTitle := ""
	userInputDevBranch := ""
	if val, err := goinp.AskForString("What's the BITRISE_APP_TITLE?"); err != nil {
		log.Fatalf("Failed to ask for input, error: %s", err)
	} else {
		userInputProjectTitle = val
	}
	if val, err := goinp.AskForString("What's your development branch's name?"); err != nil {
		log.Fatalf("Failed to ask for input, error: %s", err)
	} else {
		userInputDevBranch = val
	}

	bitriseConfContent, warnings, err := generateBitriseYMLContent(userInputProjectTitle, userInputDevBranch)
	for _, warning := range warnings {
		log.Warnf("warning: %s", warning)
	}
	if err != nil {
		log.Fatalf("Invalid Bitrise YML, error: %s", err)
	}

	if err := fileutil.WriteStringToFile(bitriseConfigFileRelPath, bitriseConfContent); err != nil {
		log.Fatalf("Failed to init the bitrise config file, error: %s", err)
	} else {
		fmt.Println()
		fmt.Println("# NOTES about the " + DefaultBitriseConfigFileName + " config file:")
		fmt.Println()
		fmt.Println("We initialized a " + DefaultBitriseConfigFileName + " config file for you.")
		fmt.Println("If you're in this folder you can use this config file")
		fmt.Println(" with bitrise automatically, you don't have to")
		fmt.Println(" specify it's path.")
		fmt.Println()
	}

	if initialized, err := saveSecretsToFile(bitriseSecretsFileRelPath, defaultSecretsContent); err != nil {
		log.Fatalf("Failed to init the secrets file, error: %s", err)
	} else if initialized {
		fmt.Println()
		fmt.Println("# NOTES about the " + DefaultSecretsFileName + " secrets file:")
		fmt.Println()
		fmt.Println("We also created a " + DefaultSecretsFileName + " file")
		fmt.Println(" in this directory, to keep your passwords, absolute path configurations")
		fmt.Println(" and other secrets separate from your")
		fmt.Println(" main configuration file.")
		fmt.Println("This way you can safely commit and share your configuration file")
		fmt.Println(" and ignore this secrets file, so nobody else will")
		fmt.Println(" know about your secrets.")
		fmt.Println(colorstring.Yellow("You should NEVER commit this secrets file into your repository!!"))
		fmt.Println()
	}

	// add the general .bitrise* item
	//  which will include both secret files like .bitrise.secrets.yml
	//  and the .bitrise work temp dir
	if err := addToGitignore(".bitrise*"); err != nil {
		log.Fatalf("Failed to add .gitignore pattern, error: %s", err)
	}
	fmt.Println(colorstring.Green("For your convenience we added the pattern '.bitrise*' to your .gitignore file"))
	fmt.Println(" to make it sure that no secrets or temporary work directories will be")
	fmt.Println(" committed into your repository.")

	fmt.Println()
	fmt.Println("Hurray, you're good to go!")
	fmt.Println("You can simply run:")
	fmt.Println("-> bitrise run test")
	fmt.Println("to test the sample configuration (which contains")
	fmt.Println("an example workflow called 'test').")
	fmt.Println()
	fmt.Println("Once you tested this sample setup you can")
	fmt.Println(" open the " + DefaultBitriseConfigFileName + " config file,")
	fmt.Println(" modify it and then run a workflow with:")
	fmt.Println("-> bitrise run YOUR-WORKFLOW-NAME")
	fmt.Println(" or trigger a build with a pattern:")
	fmt.Println("-> bitrise trigger YOUR/PATTERN")

	return nil
}
Beispiel #20
0
func printFinishStart(specPth string, toolMode bool) {
	fmt.Println()
	log.Info(" * "+colorstring.Green("[OK]")+" You can find your StepLib repo at: ", specPth)
	fmt.Println()
	fmt.Println("   " + GuideTextForShareCreate(toolMode))
}
Beispiel #21
0
func scanXamarinProject(cmd *cobra.Command, args []string) error {
	absExportOutputDirPath, err := initExportOutputDir()
	if err != nil {
		return printXamarinScanFinishedWithError("Failed to prepare Export directory: %s", err)
	}

	logOutput := ""
	xamarinCmd := xamarin.CommandModel{}
	if paramXamarinOutputLogFilePath != "" {
		xamLog, err := fileutil.ReadStringFromFile(paramXamarinOutputLogFilePath)
		if err != nil {
			return printXamarinScanFinishedWithError("Failed to read log from the specified log file, error: %s", err)
		}
		logOutput = xamLog
	} else {
		// --- Inputs ---

		// Xamarin Solution Path
		xamarinCmd.SolutionFilePath = paramXamarinSolutionFilePath
		if xamarinCmd.SolutionFilePath == "" {
			askText := `Please drag-and-drop your Xamarin Solution (` + colorstring.Green(".sln") + `)
   file here, and then hit Enter`
			fmt.Println()
			projpth, err := goinp.AskForPath(askText)
			if err != nil {
				return printXamarinScanFinishedWithError("Failed to read input: %s", err)
			}
			xamarinCmd.SolutionFilePath = projpth
		}
		log.Debugf("xamSolutionPth: %s", xamarinCmd.SolutionFilePath)

		xamSln, err := solution.New(xamarinCmd.SolutionFilePath, true)
		if err != nil {
			return printXamarinScanFinishedWithError("Failed to analyze Xamarin solution: %s", err)
		}
		log.Debugf("xamSln: %#v", xamSln)
		// filter only the iOS "app"" projects
		xamarinProjectsToChooseFrom := []project.Model{}
		for _, aXamarinProject := range xamSln.ProjectMap {
			switch aXamarinProject.ProjectType {
			case constants.ProjectTypeIOS, constants.ProjectTypeTvOS, constants.ProjectTypeMacOS:
				if aXamarinProject.OutputType == "exe" {
					// possible project
					xamarinProjectsToChooseFrom = append(xamarinProjectsToChooseFrom, aXamarinProject)
				}
			default:
				continue
			}
		}
		log.Debugf("len(xamarinProjectsToChooseFrom): %#v", len(xamarinProjectsToChooseFrom))
		log.Debugf("xamarinProjectsToChooseFrom: %#v", xamarinProjectsToChooseFrom)

		// Xamarin Project
		selectedXamarinProject := project.Model{}
		{
			if len(xamarinProjectsToChooseFrom) < 1 {
				return printXamarinScanFinishedWithError(
					"No acceptable Project found in the provided Solution, or none can be used for iOS Archive.",
				)
			}

			if paramXamarinProjectName != "" {
				// project specified via flag/param
				for _, aProj := range xamarinProjectsToChooseFrom {
					if paramXamarinProjectName == aProj.Name {
						selectedXamarinProject = aProj
						break
					}
				}
				if selectedXamarinProject.Name == "" {
					return printXamarinScanFinishedWithError(
						`Invalid Project specified (%s), either not found in the provided Solution or it can't be used for iOS "Archive for Publishing".`,
						paramXamarinProjectName)
				}
			} else {
				// no project CLI param specified
				if len(xamarinProjectsToChooseFrom) == 1 {
					selectedXamarinProject = xamarinProjectsToChooseFrom[0]
				} else {
					projectNames := []string{}
					for _, aProj := range xamarinProjectsToChooseFrom {
						projectNames = append(projectNames, aProj.Name)
					}
					fmt.Println()
					answerValue, err := goinp.SelectFromStrings(
						`Select the Project Name you use for "Archive for Publishing" (usually ends with ".iOS", e.g.: MyProject.iOS)?`,
						projectNames,
					)
					if err != nil {
						return printXamarinScanFinishedWithError("Failed to select Project: %s", err)
					}
					log.Debugf("selected project: %v", answerValue)
					for _, aProj := range xamarinProjectsToChooseFrom {
						if answerValue == aProj.Name {
							selectedXamarinProject = aProj
							break
						}
					}
				}
			}
		}
		xamarinCmd.ProjectName = selectedXamarinProject.Name
		log.Debugf("xamarinCmd.ProjectName: %s", xamarinCmd.ProjectName)

		log.Debugf("selectedXamarinProject.Configs: %#v", selectedXamarinProject.Configs)

		// Xamarin Configuration Name
		selectedXamarinConfigurationName := ""
		{
			acceptableConfigs := []string{}
			for configName, aConfig := range selectedXamarinProject.Configs {
				if aConfig.Platform == "iPhone" {
					if aConfig.Configuration == "Release" {
						// ios & tvOS app
						acceptableConfigs = append(acceptableConfigs, configName)
					}
				} else if aConfig.Platform == "x86" {
					if aConfig.Configuration == "Release" || aConfig.Configuration == "Debug" {
						// MacOS app
						acceptableConfigs = append(acceptableConfigs, configName)
					}
				}
			}
			if len(acceptableConfigs) < 1 {
				return printXamarinScanFinishedWithError(
					`No acceptable Configuration found in the provided Solution and Project, or none can be used for iOS "Archive for Publishing".`,
				)
			}

			if paramXamarinConfigurationName != "" {
				// configuration specified via flag/param
				for _, aConfigName := range acceptableConfigs {
					if paramXamarinConfigurationName == aConfigName {
						selectedXamarinConfigurationName = aConfigName
						break
					}
				}
				if selectedXamarinConfigurationName == "" {
					return printXamarinScanFinishedWithError(
						"Invalid Configuration specified (%s), either not found in the provided Solution and Project or it can't be used for iOS Archive.",
						paramXamarinConfigurationName)
				}
			} else {
				// no configuration CLI param specified
				if len(acceptableConfigs) == 1 {
					selectedXamarinConfigurationName = acceptableConfigs[0]
				} else {
					fmt.Println()
					answerValue, err := goinp.SelectFromStrings(
						`Select the Configuration Name you use for "Archive for Publishing" (usually Release|iPhone)?`,
						acceptableConfigs,
					)
					if err != nil {
						return printXamarinScanFinishedWithError("Failed to select Configuration: %s", err)
					}
					log.Debugf("selected configuration: %v", answerValue)
					selectedXamarinConfigurationName = answerValue
				}
			}
		}
		if selectedXamarinConfigurationName == "" {
			return printXamarinScanFinishedWithError(
				`No acceptable Configuration found (it was empty) in the provided Solution and Project, or none can be used for iOS "Archive for Publishing".`,
			)
		}
		xamarinCmd.ConfigurationName = selectedXamarinConfigurationName

		fmt.Println()
		fmt.Println()
		log.Println(`🔦  Running a Build, to get all the required code signing settings...`)
		xamLogOut, err := xamarinCmd.GenerateLog()
		logOutput = xamLogOut
		// save the xamarin output into a debug log file
		logOutputFilePath := filepath.Join(absExportOutputDirPath, "xamarin-build-output.log")
		{
			log.Infof("  💡  "+colorstring.Yellow("Saving xamarin output into file")+": %s", logOutputFilePath)
			if logWriteErr := fileutil.WriteStringToFile(logOutputFilePath, logOutput); logWriteErr != nil {
				log.Errorf("Failed to save xamarin build output into file (%s), error: %s", logOutputFilePath, logWriteErr)
			} else if err != nil {
				log.Infoln(colorstring.Yellow("Please check the logfile (" + logOutputFilePath + ") to see what caused the error"))
				log.Infoln(colorstring.Red(`and make sure that you can "Archive for Publishing" this project from Xamarin!`))
				fmt.Println()
				log.Infoln("Open the project: ", xamarinCmd.SolutionFilePath)
				log.Infoln(`And do "Archive for Publishing", after selecting the Configuration: `, xamarinCmd.ConfigurationName)
				fmt.Println()
			}
		}
		if err != nil {
			return printXamarinScanFinishedWithError("Failed to run xamarin build command: %s", err)
		}
	}

	codeSigningSettings, err := xamarinCmd.ScanCodeSigningSettings(logOutput)
	if err != nil {
		return printXamarinScanFinishedWithError("Failed to detect code signing settings: %s", err)
	}
	log.Debugf("codeSigningSettings: %#v", codeSigningSettings)

	return exportCodeSigningFiles("Xamarin Studio", absExportOutputDirPath, codeSigningSettings)
}
Beispiel #22
0
func printWorkflList(workflowList map[string]map[string]string, format string, minimal bool) error {
	printRawWorkflowMap := func(name string, workflow map[string]string) {
		fmt.Printf("⚡️ %s\n", colorstring.Green(name))
		fmt.Printf("  %s: %s\n", colorstring.Yellow("Summary"), workflow["summary"])
		if !minimal {
			fmt.Printf("  %s: %s\n", colorstring.Yellow("Description"), workflow["description"])
		}
		fmt.Println()
	}

	switch format {
	case output.FormatRaw:
		workflowNames := []string{}
		utilityWorkflowNames := []string{}

		for wfName := range workflowList {
			if strings.HasPrefix(wfName, "_") {
				utilityWorkflowNames = append(utilityWorkflowNames, wfName)
			} else {
				workflowNames = append(workflowNames, wfName)
			}
		}
		sort.Strings(workflowNames)
		sort.Strings(utilityWorkflowNames)

		fmt.Println()

		if len(workflowNames) > 0 {
			fmt.Printf("%s\n", "Workflows")
			fmt.Printf("%s\n", "---------")
			for _, name := range workflowNames {
				workflow := workflowList[name]
				printRawWorkflowMap(name, workflow)
			}
			fmt.Println()
		}

		if len(utilityWorkflowNames) > 0 {
			fmt.Printf("%s\n", "Util Workflows")
			fmt.Printf("%s\n", "--------------")
			for _, name := range utilityWorkflowNames {
				workflow := workflowList[name]
				printRawWorkflowMap(name, workflow)
			}
			fmt.Println()
		}

		if len(workflowNames) == 0 && len(utilityWorkflowNames) == 0 {
			fmt.Printf("Config doesn't contain any workflow")
		}

	case output.FormatJSON:
		bytes, err := json.Marshal(workflowList)
		if err != nil {
			return err
		}
		fmt.Println(string(bytes))
	default:
		return fmt.Errorf("Invalid output format: %s", format)
	}
	return nil
}
Beispiel #23
0
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
	if len(step.Dependencies) > 0 {
		log.Warnf("step.dependencies is deprecated... Use step.deps instead.")
	}

	if len(step.Deps.Brew) > 0 || len(step.Deps.AptGet) > 0 || len(step.Deps.CheckOnly) > 0 {
		//
		// New dependency handling
		for _, checkOnlyDep := range step.Deps.CheckOnly {
			if err := bitrise.DependencyTryCheckTool(checkOnlyDep.Name); err != nil {
				return 1, []envmanModels.EnvironmentItemModel{}, err
			}
			log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", checkOnlyDep.Name)
		}

		switch runtime.GOOS {
		case "darwin":
			for _, brewDep := range step.Deps.Brew {
				if err := bitrise.InstallWithBrewIfNeeded(brewDep.Name, configs.IsCIMode); err != nil {
					log.Infof("Failed to install (%s) with brew", brewDep.Name)
					return 1, []envmanModels.EnvironmentItemModel{}, err
				}
				log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", brewDep.Name)
			}
		case "linux":
			for _, aptGetDep := range step.Deps.AptGet {
				log.Infof("Start installing (%s) with apt-get", aptGetDep.Name)
				if err := bitrise.InstallWithAptGetIfNeeded(aptGetDep.Name, configs.IsCIMode); err != nil {
					log.Infof("Failed to install (%s) with apt-get", aptGetDep.Name)
					return 1, []envmanModels.EnvironmentItemModel{}, err
				}
				log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", aptGetDep.Name)
			}
		default:
			return 1, []envmanModels.EnvironmentItemModel{}, errors.New("Unsupported os")
		}
	} else if len(step.Dependencies) > 0 {
		log.Info("Deprecated dependencies found")
		//
		// Deprecated dependency handling
		for _, dep := range step.Dependencies {
			isSkippedBecauseOfPlatform := false
			switch dep.Manager {
			case depManagerBrew:
				if runtime.GOOS == "darwin" {
					err := bitrise.InstallWithBrewIfNeeded(dep.Name, configs.IsCIMode)
					if err != nil {
						return 1, []envmanModels.EnvironmentItemModel{}, err
					}
				} else {
					isSkippedBecauseOfPlatform = true
				}
				break
			case depManagerTryCheck:
				err := bitrise.DependencyTryCheckTool(dep.Name)
				if err != nil {
					return 1, []envmanModels.EnvironmentItemModel{}, err
				}
				break
			default:
				return 1, []envmanModels.EnvironmentItemModel{}, errors.New("Not supported dependency (" + dep.Manager + ") (" + dep.Name + ")")
			}

			if isSkippedBecauseOfPlatform {
				log.Debugf(" * Dependency (%s) skipped, manager (%s) not supported on this platform (%s)", dep.Name, dep.Manager, runtime.GOOS)
			} else {
				log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", dep.Name)
			}
		}
	}

	// Collect step inputs
	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
	}

	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
	stepCmd := filepath.Join(stepDir, "step.sh")
	cmd := []string{"bash", stepCmd}
	bitriseSourceDir, err := getCurrentBitriseSourceDir(environments)
	if err != nil {
		return 1, []envmanModels.EnvironmentItemModel{}, err
	}
	if bitriseSourceDir == "" {
		bitriseSourceDir = configs.CurrentDir
	}

	if exit, err := tools.EnvmanRun(configs.InputEnvstorePath, bitriseSourceDir, cmd); 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
}
Beispiel #24
0
func run(c *cli.Context) error {
	PrintBitriseHeaderASCIIArt(version.VERSION)

	//
	// Expand cli.Context
	var prGlobalFlagPtr *bool
	if c.GlobalIsSet(PRKey) {
		prGlobalFlagPtr = pointers.NewBoolPtr(c.GlobalBool(PRKey))
	}

	var ciGlobalFlagPtr *bool
	if c.GlobalIsSet(CIKey) {
		ciGlobalFlagPtr = pointers.NewBoolPtr(c.GlobalBool(CIKey))
	}

	workflowToRunID := c.String(WorkflowKey)
	if workflowToRunID == "" && len(c.Args()) > 0 {
		workflowToRunID = c.Args()[0]
	}

	bitriseConfigBase64Data := c.String(ConfigBase64Key)
	bitriseConfigPath := c.String(ConfigKey)
	deprecatedBitriseConfigPath := c.String(PathKey)
	if bitriseConfigPath == "" && deprecatedBitriseConfigPath != "" {
		log.Warn("'path' key is deprecated, use 'config' instead!")
		bitriseConfigPath = deprecatedBitriseConfigPath
	}

	inventoryBase64Data := c.String(InventoryBase64Key)
	inventoryPath := c.String(InventoryKey)

	jsonParams := c.String(JSONParamsKey)
	jsonParamsBase64 := c.String(JSONParamsBase64Key)

	runParams, err := parseRunParams(
		workflowToRunID,
		bitriseConfigPath, bitriseConfigBase64Data,
		inventoryPath, inventoryBase64Data,
		jsonParams, jsonParamsBase64)
	if err != nil {
		return fmt.Errorf("Failed to parse command params, error: %s", err)
	}
	//

	// Inventory validation
	inventoryEnvironments, err := CreateInventoryFromCLIParams(runParams.InventoryBase64Data, runParams.InventoryPath)
	if err != nil {
		log.Fatalf("Failed to create inventory, error: %s", err)
	}

	// Config validation
	bitriseConfig, warnings, err := CreateBitriseConfigFromCLIParams(runParams.BitriseConfigBase64Data, runParams.BitriseConfigPath)
	for _, warning := range warnings {
		log.Warnf("warning: %s", warning)
	}
	if err != nil {
		log.Fatalf("Failed to create bitrise config, error: %s", err)
	}

	// Workflow id validation
	if runParams.WorkflowToRunID == "" {
		// no workflow specified
		//  list all the available ones and then exit
		log.Error("No workfow specified!")
		fmt.Println()
		printAvailableWorkflows(bitriseConfig)
		os.Exit(1)
	}
	if strings.HasPrefix(runParams.WorkflowToRunID, "_") {
		// util workflow specified
		//  print about util workflows and then exit
		log.Error("Utility workflows can't be triggered directly")
		fmt.Println()
		printAboutUtilityWorkflowsText()
		os.Exit(1)
	}
	//

	//
	// Main
	isPRMode, err := isPRMode(prGlobalFlagPtr, inventoryEnvironments)
	if err != nil {
		log.Fatalf("Failed to check  PR mode, error: %s", err)
	}

	if err := registerPrMode(isPRMode); err != nil {
		log.Fatalf("Failed to register  PR mode, error: %s", err)
	}

	isCIMode, err := isCIMode(ciGlobalFlagPtr, inventoryEnvironments)
	if err != nil {
		log.Fatalf("Failed to check  CI mode, error: %s", err)
	}

	if err := registerCIMode(isCIMode); err != nil {
		log.Fatalf("Failed to register  CI mode, error: %s", err)
	}

	log.Infoln(colorstring.Green("Running workflow:"), runParams.WorkflowToRunID)

	runAndExit(bitriseConfig, inventoryEnvironments, runParams.WorkflowToRunID)
	//

	return nil
}
Beispiel #25
0
func runStep(step stepmanModels.StepModel, stepIDData models.StepIDData, stepDir string, environments []envmanModels.EnvironmentItemModel) (int, []envmanModels.EnvironmentItemModel, error) {
	log.Debugf("[BITRISE_CLI] - Try running step: %s (%s)", stepIDData.IDorURI, stepIDData.Version)

	// Check dependencies
	for _, dep := range step.Dependencies {
		isSkippedBecauseOfPlatform := false
		switch dep.Manager {
		case depManagerBrew:
			if runtime.GOOS == "darwin" {
				err := bitrise.InstallWithBrewIfNeeded(dep.Name, IsCIMode)
				if err != nil {
					return 1, []envmanModels.EnvironmentItemModel{}, err
				}
			} else {
				isSkippedBecauseOfPlatform = true
			}
			break
		case depManagerTryCheck:
			err := bitrise.DependencyTryCheckTool(dep.Name)
			if err != nil {
				return 1, []envmanModels.EnvironmentItemModel{}, err
			}
			break
		default:
			return 1, []envmanModels.EnvironmentItemModel{}, errors.New("Not supported dependency (" + dep.Manager + ") (" + dep.Name + ")")
		}

		if isSkippedBecauseOfPlatform {
			log.Debugf(" * Dependency (%s) skipped, manager (%s) not supported on this platform (%s)", dep.Name, dep.Manager, runtime.GOOS)
		} else {
			log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", dep.Name)
		}
	}

	// Collect step inputs
	environments = append(environments, step.Inputs...)

	// Cleanup envstore
	if err := bitrise.EnvmanInitAtPath(bitrise.InputEnvstorePath); err != nil {
		return 1, []envmanModels.EnvironmentItemModel{}, err
	}
	if err := bitrise.ExportEnvironmentsList(environments); err != nil {
		return 1, []envmanModels.EnvironmentItemModel{}, err
	}

	// Run step
	stepCmd := path.Join(stepDir, "step.sh")
	log.Debug("OUTPUT:")
	cmd := []string{"bash", stepCmd}
	if exit, err := bitrise.EnvmanRun(bitrise.InputEnvstorePath, bitrise.CurrentDir, cmd, "panic"); err != nil {
		return exit, []envmanModels.EnvironmentItemModel{}, err
	}

	stepOutputs, err := bitrise.CollectEnvironmentsFromFile(bitrise.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
}
Beispiel #26
0
func checkAndInstallStepDependencies(step stepmanModels.StepModel) error {
	if len(step.Dependencies) > 0 {
		log.Warnf("step.dependencies is deprecated... Use step.deps instead.")
	}

	if len(step.Deps.Brew) > 0 || len(step.Deps.AptGet) > 0 || len(step.Deps.CheckOnly) > 0 {
		//
		// New dependency handling
		for _, checkOnlyDep := range step.Deps.CheckOnly {
			if err := bitrise.DependencyTryCheckTool(checkOnlyDep.Name); err != nil {
				return err
			}
			log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", checkOnlyDep.Name)
		}

		switch runtime.GOOS {
		case "darwin":
			for _, brewDep := range step.Deps.Brew {
				if err := bitrise.InstallWithBrewIfNeeded(brewDep, configs.IsCIMode); err != nil {
					log.Infof("Failed to install (%s) with brew", brewDep.Name)
					return err
				}
				log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", brewDep.Name)
			}
		case "linux":
			for _, aptGetDep := range step.Deps.AptGet {
				log.Infof("Start installing (%s) with apt-get", aptGetDep.Name)
				if err := bitrise.InstallWithAptGetIfNeeded(aptGetDep, configs.IsCIMode); err != nil {
					log.Infof("Failed to install (%s) with apt-get", aptGetDep.Name)
					return err
				}
				log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", aptGetDep.Name)
			}
		default:
			return errors.New("Unsupported os")
		}
	} else if len(step.Dependencies) > 0 {
		log.Info("Deprecated dependencies found")
		//
		// Deprecated dependency handling
		for _, dep := range step.Dependencies {
			isSkippedBecauseOfPlatform := false
			switch dep.Manager {
			case depManagerBrew:
				if runtime.GOOS == "darwin" {
					err := bitrise.InstallWithBrewIfNeeded(stepmanModels.BrewDepModel{Name: dep.Name}, configs.IsCIMode)
					if err != nil {
						return err
					}
				} else {
					isSkippedBecauseOfPlatform = true
				}
				break
			case depManagerTryCheck:
				err := bitrise.DependencyTryCheckTool(dep.Name)
				if err != nil {
					return err
				}
				break
			default:
				return errors.New("Not supported dependency (" + dep.Manager + ") (" + dep.Name + ")")
			}

			if isSkippedBecauseOfPlatform {
				log.Debugf(" * Dependency (%s) skipped, manager (%s) not supported on this platform (%s)", dep.Name, dep.Manager, runtime.GOOS)
			} else {
				log.Infof(" * "+colorstring.Green("[OK]")+" Step dependency (%s) installed, available.", dep.Name)
			}
		}
	}

	return nil
}
Beispiel #27
0
func printFinishAudit(share ShareModel, toolMode bool) {
	fmt.Println()
	log.Infof(" * "+colorstring.Green("[OK]")+" Your step (%s) (%s) is valid.", share.StepID, share.StepTag)
	fmt.Println()
	fmt.Println("   " + GuideTextForShareFinish(toolMode))
}
Beispiel #28
0
// 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
}
Beispiel #29
0
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
}
Beispiel #30
0
func (plugin Plugin) String() string {
	pluginStr := colorstring.Green(plugin.Name)
	pluginStr += fmt.Sprintf("\n  Description: %s", plugin.Description)
	return pluginStr
}