예제 #1
0
파일: step_info.go 프로젝트: godrei/stepman
func printRawStepInfo(stepInfo models.StepInfoModel, isShort, isLocal bool) {
	if isLocal {
		fmt.Println(colorstring.Bluef("Local step info, yml path (%s):", stepInfo.StepLib))
	} else {
		fmt.Println(colorstring.Bluef("Step info in StepLib (%s):", stepInfo.StepLib))
	}

	if stepInfo.GlobalInfo.RemovalDate != "" {
		fmt.Println("")
		fmt.Println(colorstring.Red("This step is deprecated!"))
		fmt.Printf("%s %s\n", colorstring.Red("removal date:"), stepInfo.GlobalInfo.RemovalDate)

		if stepInfo.GlobalInfo.DeprecateNotes != "" {
			fmt.Printf("%s\n%s\n", colorstring.Red("deprecate notes:"), stepInfo.GlobalInfo.DeprecateNotes)
		}
	}

	if stepInfo.ID != "" {
		fmt.Printf("%s: %s\n", colorstring.Blue("ID"), stepInfo.ID)
	}
	if stepInfo.Version != "" {
		fmt.Printf("%s: %s\n", colorstring.Blue("version"), stepInfo.Version)
	}
	if stepInfo.Latest != "" {
		fmt.Printf("%s: %s\n", colorstring.Blue("latest"), stepInfo.Latest)
	}

	if !isShort {
		fmt.Printf("%s: %s\n", colorstring.Blue("source"), stepInfo.Source)
		fmt.Printf("%s:\n", colorstring.Blue("description"))
		fmt.Printf("%s\n", stepInfo.Description)
		fmt.Println()

		if len(stepInfo.Inputs) > 0 {
			fmt.Printf("%s:\n", colorstring.Blue("inputs"))
			for _, input := range stepInfo.Inputs {
				printRawEnvInfo(input)
			}
		}

		if len(stepInfo.Outputs) > 0 {
			if len(stepInfo.Inputs) > 0 {
				fmt.Println()
			}
			fmt.Printf("%s:\n", colorstring.Blue("outputs"))
			for _, output := range stepInfo.Outputs {
				printRawEnvInfo(output)
			}
		}
	}

	fmt.Println()
	fmt.Println()
}
예제 #2
0
func printFinishedWithError(toolName, format string, args ...interface{}) error {
	fmt.Println()
	fmt.Println("------------------------------")
	fmt.Println("First of all " + colorstring.Red("please make sure that you can Archive your app from "+toolName+"."))
	fmt.Println("codesigndoc only works if you can archive your app from " + toolName + ".")
	fmt.Println("If you can, and you get a valid IPA file if you export from " + toolName + ",")
	fmt.Println(colorstring.Red("please create an issue") + " on GitHub at: https://github.com/bitrise-tools/codesigndoc/issues")
	fmt.Println("with as many details & logs as you can share!")
	fmt.Println("------------------------------")
	fmt.Println()

	return fmt.Errorf(colorstring.Red("Error: ")+format, args...)
}
예제 #3
0
func (v ValidateResponseModel) String() string {
	if v.Error != "" {
		msg := fmt.Sprintf("%s: %s", colorstring.Red("Error"), v.Error)
		if len(v.Warnings) > 0 {
			msg += "\nWarning(s):\n"
			for i, warning := range v.Warnings {
				msg += fmt.Sprintf("- %s", warning)
				if i != len(v.Warnings)-1 {
					msg += "\n"
				}
			}
		}
		return msg
	}

	if v.Data != nil {
		msg := v.Data.String()
		if len(v.Warnings) > 0 {
			msg += "\nWarning(s):\n"
			for i, warning := range v.Warnings {
				msg += fmt.Sprintf("- %s", warning)
				if i != len(v.Warnings)-1 {
					msg += "\n"
				}
			}
		}
		return msg
	}

	return ""
}
예제 #4
0
파일: print.go 프로젝트: bitrise-io/bitrise
func getRunningStepFooterMainSection(stepRunResult models.StepRunResultsModel) string {
	iconBoxWidth := len("   ")
	timeBoxWidth := len(" time (s) ")
	titleBoxWidth := stepRunSummaryBoxWidthInChars - 4 - iconBoxWidth - timeBoxWidth - 1

	icon := ""
	title := getTrimmedStepName(stepRunResult)
	coloringFunc := colorstring.Green

	switch stepRunResult.Status {
	case models.StepRunStatusCodeSuccess:
		icon = "✓"
		coloringFunc = colorstring.Green
		break
	case models.StepRunStatusCodeFailed:
		icon = "x"
		coloringFunc = colorstring.Red
		break
	case models.StepRunStatusCodeFailedSkippable:
		icon = "!"
		coloringFunc = colorstring.Yellow
		break
	case models.StepRunStatusCodeSkipped, models.StepRunStatusCodeSkippedWithRunIf:
		icon = "-"
		coloringFunc = colorstring.Blue
		break
	default:
		log.Error("Unkown result code")
		return ""
	}

	iconBox := fmt.Sprintf(" %s ", coloringFunc(icon))

	titleWhiteSpaceWidth := titleBoxWidth - len(title)
	coloredTitle := title
	if strings.HasPrefix(title, "[Deprecated]") {
		title := strings.TrimPrefix(title, "[Deprecated]")
		coloredTitle = fmt.Sprintf("%s%s", colorstring.Red("[Deprecated]"), coloringFunc(title))
	} else {
		coloredTitle = coloringFunc(title)
	}

	titleBox := fmt.Sprintf(" %s%s", coloredTitle, strings.Repeat(" ", titleWhiteSpaceWidth))

	runTimeStr, err := FormattedSecondsToMax8Chars(stepRunResult.RunTime)
	if err != nil {
		log.Errorf("Failed to format time, error: %s", err)
		runTimeStr = "999+ hour"
	}

	timeWhiteSpaceWidth := timeBoxWidth - len(runTimeStr) - 1
	if timeWhiteSpaceWidth < 0 {
		log.Errorf("Invalid time box size for RunTime: %#v", stepRunResult.RunTime)
		timeWhiteSpaceWidth = 0
	}
	timeBox := fmt.Sprintf(" %s%s", runTimeStr, strings.Repeat(" ", timeWhiteSpaceWidth))

	return fmt.Sprintf("|%s|%s|%s|", iconBox, titleBox, timeBox)
}
예제 #5
0
func printRawValidation(validation ValidationModel) error {
	validConfig := true
	if validation.Config != nil {
		fmt.Println(colorstring.Blue("Config validation result:"))
		configValidation := *validation.Config
		if configValidation.IsValid {
			fmt.Printf("is valid: %s\n", colorstring.Greenf("%v", configValidation.IsValid))
		} else {
			fmt.Printf("is valid: %s\n", colorstring.Redf("%v", configValidation.IsValid))
			fmt.Printf("error: %s\n", colorstring.Red(configValidation.Error))

			validConfig = false
		}
		fmt.Println()
	}

	validSecrets := true
	if validation.Secrets != nil {
		fmt.Println(colorstring.Blue("Secret validation result:"))
		secretValidation := *validation.Secrets
		if secretValidation.IsValid {
			fmt.Printf("is valid: %s\n", colorstring.Greenf("%v", secretValidation.IsValid))
		} else {
			fmt.Printf("is valid: %s\n", colorstring.Redf("%v", secretValidation.IsValid))
			fmt.Printf("error: %s\n", colorstring.Red(secretValidation.Error))

			validSecrets = false
		}
	}

	if !validConfig && !validSecrets {
		return errors.New("Config and secrets are invalid")
	} else if !validConfig {
		return errors.New("Config is invalid")
	} else if !validSecrets {
		return errors.New("Secret is invalid")
	}
	return nil
}
예제 #6
0
// String ...
func (v ValidationModel) String() string {
	msg := ""

	if v.Config != nil {
		config := *v.Config
		if config.IsValid {
			msg += fmt.Sprintf("Config is valid: %s", colorstring.Greenf("%v", true))
		} else {
			msg += fmt.Sprintf("Config is valid: %s", colorstring.Redf("%v", false))
			msg += fmt.Sprintf("\nError: %s", colorstring.Red(config.Error))
		}

		if len(config.Warnings) > 0 {
			msg += "\nWarning(s):\n"
			for i, warning := range config.Warnings {
				msg += fmt.Sprintf("- %s", warning)
				if i != len(config.Warnings)-1 {
					msg += "\n"
				}
			}
		}
	}

	if v.Secrets != nil {
		if v.Config != nil {
			msg += "\n"
		}

		secret := *v.Secrets
		if secret.IsValid {
			msg += fmt.Sprintf("Secret is valid: %s", colorstring.Greenf("%v", true))
		} else {
			msg += fmt.Sprintf("Secret is valid: %s", colorstring.Redf("%v", false))
			msg += fmt.Sprintf("\nError: %s", colorstring.Red(secret.Error))
		}
	}

	return msg
}
예제 #7
0
func getRunningStepFooterMainSection(stepRunResult models.StepRunResultsModel) string {
	iconBoxWidth := len("    ")
	timeBoxWidth := len(" time (s) ")
	titleBoxWidth := stepRunSummaryBoxWidthInChars - 4 - iconBoxWidth - timeBoxWidth - 1

	icon := ""
	title := getTrimmedStepName(stepRunResult)
	runTimeStr := TimeToFormattedSeconds(stepRunResult.RunTime, " sec")
	coloringFunc := colorstring.Green

	switch stepRunResult.Status {
	case models.StepRunStatusCodeSuccess:
		icon = "✅"
		coloringFunc = colorstring.Green
		break
	case models.StepRunStatusCodeFailed:
		icon = "🚫"
		coloringFunc = colorstring.Red
		break
	case models.StepRunStatusCodeFailedSkippable:
		icon = "⚠�"
		coloringFunc = colorstring.Yellow
		break
	case models.StepRunStatusCodeSkipped, models.StepRunStatusCodeSkippedWithRunIf:
		icon = "âž¡"
		coloringFunc = colorstring.Blue
		break
	default:
		log.Error("Unkown result code")
		return ""
	}

	iconBox := fmt.Sprintf(" %s  ", icon)

	titleWhiteSpaceWidth := titleBoxWidth - len(title)
	coloredTitle := title
	if strings.HasPrefix(title, "[Deprecated]") {
		title := strings.TrimPrefix(title, "[Deprecated]")
		coloredTitle = fmt.Sprintf("%s%s", colorstring.Red("[Deprecated]"), coloringFunc(title))
	} else {
		coloredTitle = coloringFunc(title)
	}

	titleBox := fmt.Sprintf(" %s%s", coloredTitle, strings.Repeat(" ", titleWhiteSpaceWidth))

	timeWhiteSpaceWidth := timeBoxWidth - len(runTimeStr) - 1
	timeBox := fmt.Sprintf(" %s%s", runTimeStr, strings.Repeat(" ", timeWhiteSpaceWidth))

	return fmt.Sprintf("|%s|%s|%s|", iconBox, titleBox, timeBox)
}
예제 #8
0
func getRunningStepFooterSubSection(stepRunResult models.StepRunResultsModel) string {
	stepInfo := stepRunResult.StepInfo

	removalDate := stepInfo.GlobalInfo.RemovalDate
	deprecateNotes := stepInfo.GlobalInfo.DeprecateNotes
	removalDateRow := ""
	deprecateNotesRow := ""
	if removalDate != "" {
		removalDateValue := removalDate
		removalDateKey := colorstring.Red("Removal date:")

		removalDateRow = fmt.Sprintf("| Removal date: %s |", removalDateValue)
		charDiff := len(removalDateRow) - stepRunSummaryBoxWidthInChars
		removalDateRow = fmt.Sprintf("| %s %s%s |", removalDateKey, removalDateValue, strings.Repeat(" ", -charDiff))

		if deprecateNotes != "" {
			deprecateNotesStr := fmt.Sprintf("Removal notes: %s", deprecateNotes)
			deprecateNotesRow = getDeprecateNotesRows(deprecateNotesStr)
		}
	}

	isUpdateAvailable := isUpdateAvailable(stepRunResult.StepInfo)
	updateRow := ""
	if isUpdateAvailable {
		updateRow = fmt.Sprintf("| Update available: %s -> %s |", stepInfo.Version, stepInfo.Latest)
		charDiff := len(updateRow) - stepRunSummaryBoxWidthInChars
		if charDiff < 0 {
			// shorter than desired - fill with space
			updateRow = fmt.Sprintf("| Update available: %s -> %s%s |", stepInfo.Version, stepInfo.Latest, strings.Repeat(" ", -charDiff))
		} else if charDiff > 0 {
			// longer than desired - trim title
			if charDiff > 6 {
				updateRow = fmt.Sprintf("| Update available!%s |", strings.Repeat(" ", -len("| Update available! |")-stepRunSummaryBoxWidthInChars))
			} else {
				updateRow = fmt.Sprintf("| Update available: -> %s%s |", stepInfo.Latest, strings.Repeat(" ", -len("| Update available: -> %s |")-stepRunSummaryBoxWidthInChars))
			}
		}
	}

	issueRow := ""
	sourceRow := ""
	if stepRunResult.Error != nil {
		// Support URL
		var coloringFunc func(...interface{}) string
		supportURL := stepInfo.SupportURL
		if supportURL == "" {
			coloringFunc = colorstring.Yellow
			supportURL = "Not provided"
		}

		issueRow = fmt.Sprintf("| Issue tracker: %s |", supportURL)

		charDiff := len(issueRow) - stepRunSummaryBoxWidthInChars
		if charDiff <= 0 {
			// shorter than desired - fill with space

			if coloringFunc != nil {
				// We need to do this after charDiff calculation,
				// because of coloring characters increase the text length, but they do not printed
				supportURL = coloringFunc("Not provided")
			}

			issueRow = fmt.Sprintf("| Issue tracker: %s%s |", supportURL, strings.Repeat(" ", -charDiff))
		} else if charDiff > 0 {
			// longer than desired - trim title
			trimmedWidth := len(supportURL) - charDiff
			if trimmedWidth < 4 {
				log.Errorf("Support url too long, can't present support url at all! : %s", supportURL)
			} else {
				issueRow = fmt.Sprintf("| Issue tracker: %s |", stringutil.MaxLastCharsWithDots(supportURL, trimmedWidth))
			}
		}

		// Source Code URL
		coloringFunc = nil
		sourceCodeURL := stepInfo.SourceCodeURL
		if sourceCodeURL == "" {
			coloringFunc = colorstring.Yellow
			sourceCodeURL = "Not provided"
		}

		sourceRow = fmt.Sprintf("| Source: %s |", sourceCodeURL)

		charDiff = len(sourceRow) - stepRunSummaryBoxWidthInChars
		if charDiff <= 0 {
			// shorter than desired - fill with space

			if coloringFunc != nil {
				// We need to do this after charDiff calculation,
				// because of coloring characters increase the text length, but they do not printed
				sourceCodeURL = coloringFunc("Not provided")
			}

			sourceRow = fmt.Sprintf("| Source: %s%s |", sourceCodeURL, strings.Repeat(" ", -charDiff))
		} else if charDiff > 0 {
			// longer than desired - trim title
			trimmedWidth := len(sourceCodeURL) - charDiff
			if trimmedWidth < 4 {
				log.Errorf("Source url too long, can't present source url at all! : %s", sourceCodeURL)
			} else {
				sourceRow = fmt.Sprintf("| Source: %s |", stringutil.MaxLastCharsWithDots(sourceCodeURL, trimmedWidth))
			}
		}
	}

	// Update available
	content := ""
	if isUpdateAvailable {
		content = fmt.Sprintf("%s", updateRow)
	}

	// Support URL
	if content != "" {
		content = fmt.Sprintf("%s\n%s", content, issueRow)
	} else {
		content = fmt.Sprintf("%s", issueRow)
	}

	// Source Code URL
	if content != "" {
		content = fmt.Sprintf("%s\n%s", content, sourceRow)
	} else {
		content = fmt.Sprintf("%s", sourceRow)
	}

	// Deprecation
	if removalDate != "" {
		if content != "" {
			content = fmt.Sprintf("%s\n%s", content, removalDateRow)
		} else {
			content = fmt.Sprintf("%s", removalDateRow)
		}

		if deprecateNotes != "" {
			if content != "" {
				content = fmt.Sprintf("%s\n%s", content, deprecateNotesRow)
			} else {
				content = fmt.Sprintf("%s", deprecateNotesRow)
			}
		}
	}

	return content
}
예제 #9
0
func getDeprecateNotesRows(notes string) string {
	colorDeprecateNote := func(line string) string {
		if strings.HasPrefix(line, "Removal notes:") {
			line = strings.TrimPrefix(line, "Removal notes:")
			line = fmt.Sprintf("%s%s", colorstring.Red("Removal notes:"), line)
		}
		return line
	}

	boxContentWidth := stepRunSummaryBoxWidthInChars - 4

	notesWithoutNewLine := strings.Replace(notes, "\n", " ", -1)
	words := strings.Split(notesWithoutNewLine, " ")
	if len(words) == 0 {
		return ""
	}

	formattedNote := ""
	line := ""

	for i, word := range words {
		isLastLine := (i == len(words)-1)

		expectedLine := ""
		if line == "" {
			expectedLine = word
		} else {
			expectedLine = line + " " + word
		}

		if utf8.RuneCountInString(expectedLine) > boxContentWidth {
			// expected line would be to long, so print the previous line, and start a new with the last word.
			noteRow := fmt.Sprintf("| %s |", line)
			charDiff := len(noteRow) - stepRunSummaryBoxWidthInChars
			if charDiff <= 0 {
				// shorter than desired - fill with space
				line = colorDeprecateNote(line)
				noteRow = fmt.Sprintf("| %s%s |", line, strings.Repeat(" ", -charDiff))
			} else if charDiff > 0 {
				// longer than desired - should not
				log.Errorln("Should not be longer then expected")
			}

			if formattedNote == "" {
				formattedNote = noteRow
			} else {
				formattedNote = fmt.Sprintf("%s\n%s", formattedNote, noteRow)
			}

			line = word

			if isLastLine {
				noteRow := fmt.Sprintf("| %s |", line)
				charDiff := len(noteRow) - stepRunSummaryBoxWidthInChars
				if charDiff < 0 {
					// shorter than desired - fill with space
					line = colorDeprecateNote(line)
					noteRow = fmt.Sprintf("| %s%s |", line, strings.Repeat(" ", -charDiff))
				} else if charDiff > 0 {
					// longer than desired - should not
					log.Errorln("Should not be longer then expected")
				}

				if formattedNote == "" {
					formattedNote = noteRow
				} else {
					formattedNote = fmt.Sprintf("%s\n%s", formattedNote, noteRow)
				}
			}
		} else {
			// expected line is not to long, just keep growing the line
			line = expectedLine

			if isLastLine {
				noteRow := fmt.Sprintf("| %s |", line)
				charDiff := len(noteRow) - stepRunSummaryBoxWidthInChars
				if charDiff <= 0 {
					// shorter than desired - fill with space
					line = colorDeprecateNote(line)
					noteRow = fmt.Sprintf("| %s%s |", line, strings.Repeat(" ", -charDiff))
				} else if charDiff > 0 {
					// longer than desired - should not
					log.Errorln("Should not be longer then expected")
				}

				if formattedNote == "" {
					formattedNote = noteRow
				} else {
					formattedNote = fmt.Sprintf("%s\n%s", formattedNote, noteRow)
				}
			}
		}
	}

	return formattedNote
}
예제 #10
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)
}
예제 #11
0
// Error ...
func Error(format string, v ...interface{}) {
	message := fmt.Sprintf(format, v...)
	fmt.Println(colorstring.Red(message))
}
예제 #12
0
func scanXcodeProject(cmd *cobra.Command, args []string) error {
	absExportOutputDirPath, err := initExportOutputDir()
	if err != nil {
		return printXcodeScanFinishedWithError("Failed to prepare Export directory: %s", err)
	}

	xcodebuildOutput := ""
	xcodeCmd := xcode.CommandModel{}
	if paramXcodebuildOutputLogFilePath != "" {
		xcLog, err := fileutil.ReadStringFromFile(paramXcodebuildOutputLogFilePath)
		if err != nil {
			return printXcodeScanFinishedWithError("Failed to read log from the specified log file, error: %s", err)
		}
		xcodebuildOutput = xcLog
	} else {
		projectPath := paramXcodeProjectFilePath
		if projectPath == "" {
			askText := `Please drag-and-drop your Xcode Project (` + colorstring.Green(".xcodeproj") + `)
   or Workspace (` + colorstring.Green(".xcworkspace") + `) file, the one you usually open in Xcode,
   then hit Enter.

  (Note: if you have a Workspace file you should most likely use that)`
			fmt.Println()
			projpth, err := goinp.AskForPath(askText)
			if err != nil {
				return printXcodeScanFinishedWithError("Failed to read input: %s", err)
			}
			projectPath = projpth
		}
		log.Debugf("projectPath: %s", projectPath)
		xcodeCmd.ProjectFilePath = projectPath

		schemeToUse := paramXcodeScheme
		if schemeToUse == "" {
			fmt.Println()
			fmt.Println()
			log.Println("🔦  Scanning Schemes ...")
			schemes, err := xcodeCmd.ScanSchemes()
			if err != nil {
				return printXcodeScanFinishedWithError("Failed to scan Schemes: %s", err)
			}
			log.Debugf("schemes: %v", schemes)

			fmt.Println()
			selectedScheme, err := goinp.SelectFromStrings("Select the Scheme you usually use in Xcode", schemes)
			if err != nil {
				return printXcodeScanFinishedWithError("Failed to select Scheme: %s", err)
			}
			log.Debugf("selected scheme: %v", selectedScheme)
			schemeToUse = selectedScheme
		}
		xcodeCmd.Scheme = schemeToUse

		fmt.Println()
		fmt.Println()
		log.Println("🔦  Running an Xcode Archive, to get all the required code signing settings...")
		xcLog, err := xcodeCmd.GenerateLog()
		xcodebuildOutput = xcLog
		// save the xcodebuild output into a debug log file
		xcodebuildOutputFilePath := filepath.Join(absExportOutputDirPath, "xcodebuild-output.log")
		{
			log.Infof("  💡  "+colorstring.Yellow("Saving xcodebuild output into file")+": %s", xcodebuildOutputFilePath)
			if logWriteErr := fileutil.WriteStringToFile(xcodebuildOutputFilePath, xcodebuildOutput); logWriteErr != nil {
				log.Errorf("Failed to save xcodebuild output into file (%s), error: %s", xcodebuildOutputFilePath, logWriteErr)
			} else if err != nil {
				log.Infoln(colorstring.Yellow("Please check the logfile (" + xcodebuildOutputFilePath + ") to see what caused the error"))
				log.Infoln(colorstring.Red("and make sure that you can Archive this project from Xcode!"))
				fmt.Println()
				log.Infoln("Open the project:", xcodeCmd.ProjectFilePath)
				log.Infoln("and Archive, using the Scheme:", xcodeCmd.Scheme)
				fmt.Println()
			}
		}
		if err != nil {
			return printXcodeScanFinishedWithError("Failed to run Xcode Archive: %s", err)
		}
	}

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

	return exportCodeSigningFiles("Xcode", absExportOutputDirPath, codeSigningSettings)
}