Пример #1
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
}
Пример #2
0
// GuideTextForAudit ...
func GuideTextForAudit(toolMode bool) string {
	name := "stepman"
	if toolMode {
		name = "bitrise"
	}

	guide := "You can call " + colorstring.Blue("'"+name+" audit'") + `,
   to perform a complete health-check on your StepLib before submitting your Pull Request.
   This can help you catch issues which might prevent your Step to be accepted.
   `
	return guide
}
Пример #3
0
func triggerCheck(c *cli.Context) {
	format := c.String(OuputFormatKey)
	if format == "" {
		format = configs.OutputFormatRaw
	} else if !(format == configs.OutputFormatRaw || format == configs.OutputFormatJSON) {
		registerFatal(fmt.Sprintf("Invalid format: %s", format), configs.OutputFormatJSON)
	}

	// Config validation
	bitriseConfig, err := CreateBitriseConfigFromCLIParams(c)
	if err != nil {
		registerFatal(fmt.Sprintf("Failed to create config, err: %s", err), format)
	}

	// Trigger filter validation
	triggerPattern := ""
	if len(c.Args()) < 1 {
		registerFatal("No trigger pattern specified", format)
	} else {
		triggerPattern = c.Args()[0]
	}

	if triggerPattern == "" {
		registerFatal("No trigger pattern specified", format)
	}

	workflowToRunID, err := GetWorkflowIDByPattern(bitriseConfig, triggerPattern)
	if err != nil {
		registerFatal(err.Error(), format)
	}

	switch format {
	case configs.OutputFormatRaw:
		fmt.Printf("%s -> %s\n", triggerPattern, colorstring.Blue(workflowToRunID))
		break
	case configs.OutputFormatJSON:
		triggerModel := map[string]string{
			"pattern":  triggerPattern,
			"workflow": workflowToRunID,
		}
		bytes, err := json.Marshal(triggerModel)
		if err != nil {
			registerFatal(fmt.Sprintf("Failed to parse trigger model, err: %s", err), format)
		}

		fmt.Println(string(bytes))
		break
	default:
		registerFatal(fmt.Sprintf("Invalid format: %s", format), configs.OutputFormatJSON)
	}

}
Пример #4
0
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()
}
Пример #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
// GuideTextForShareFinish ...
func GuideTextForShareFinish(toolMode bool) string {
	name := "stepman"
	if toolMode {
		name = "bitrise"
	}

	guide := `Almost done! You should review your Step's step.yml file (the one added to the local StepLib),
   and once you're happy with it call: ` + colorstring.Blue("'"+name+" share finish'") + `

   This will commit & push the step.yml ` + colorstring.Yellow("into your forked StepLib repository") + `.
		`
	return guide
}
Пример #7
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
}
Пример #8
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
}
Пример #9
0
func activateAndRunSteps(workflow models.WorkflowModel, defaultStepLibSource string, buildRunResults models.BuildRunResultsModel, environments *[]envmanModels.EnvironmentItemModel, isLastWorkflow bool) models.BuildRunResultsModel {
	log.Debugln("[BITRISE_CLI] - Activating and running steps")

	var stepStartTime time.Time

	registerStepRunResults := func(step stepmanModels.StepModel, resultCode, exitCode int, err error, isLastStep bool) {
		if step.Title == nil {
			log.Error("Step title is nil, should not happend!")
			step.Title = pointers.NewStringPtr("ERROR! Step title is nil!")
		}

		stepResults := models.StepRunResultsModel{
			StepName: *step.Title,
			Status:   resultCode,
			Idx:      buildRunResults.ResultsCount(),
			RunTime:  time.Now().Sub(stepStartTime),
			Error:    err,
			ExitCode: exitCode,
		}

		switch resultCode {
		case models.StepRunStatusCodeSuccess:
			buildRunResults.SuccessSteps = append(buildRunResults.SuccessSteps, stepResults)
			break
		case models.StepRunStatusCodeFailed:
			log.Errorf("Step (%s) failed, error: (%v)", *step.Title, err)
			buildRunResults.FailedSteps = append(buildRunResults.FailedSteps, stepResults)
			break
		case models.StepRunStatusCodeFailedSkippable:
			log.Warnf("Step (%s) failed, but was marked as skippable, error: (%v)", *step.Title, err)
			buildRunResults.FailedSkippableSteps = append(buildRunResults.FailedSkippableSteps, stepResults)
			break
		case models.StepRunStatusCodeSkipped:
			log.Warnf("A previous step failed, and this step (%s) was not marked as IsAlwaysRun, skipped", *step.Title)
			buildRunResults.SkippedSteps = append(buildRunResults.SkippedSteps, stepResults)
			break
		case models.StepRunStatusCodeSkippedWithRunIf:
			log.Warn("The step's (" + *step.Title + ") Run-If expression evaluated to false - skipping")
			log.Info("The Run-If expression was: ", colorstring.Blue(*step.RunIf))
			buildRunResults.SkippedSteps = append(buildRunResults.SkippedSteps, stepResults)
			break
		default:
			log.Error("Unkown result code")
			return
		}

		bitrise.PrintStepSummary(stepResults, isLastStep)
	}

	registerStepListItemRunResults := func(stepListItem models.StepListItemModel, resultCode, exitCode int, err error, isLastStep bool) {
		name := ""
		for key := range stepListItem {
			name = key
			break
		}

		stepResults := models.StepRunResultsModel{
			StepName: name,
			Status:   resultCode,
			Idx:      buildRunResults.ResultsCount(),
			RunTime:  time.Now().Sub(stepStartTime),
			Error:    err,
			ExitCode: exitCode,
		}

		switch resultCode {
		case models.StepRunStatusCodeSuccess:
			buildRunResults.SuccessSteps = append(buildRunResults.SuccessSteps, stepResults)
			break
		case models.StepRunStatusCodeFailed:
			log.Errorf("Step (%s) failed, error: (%v)", name, err)
			buildRunResults.FailedSteps = append(buildRunResults.FailedSteps, stepResults)
			break
		case models.StepRunStatusCodeFailedSkippable:
			log.Warnf("Step (%s) failed, but was marked as skippable, error: (%v)", name, err)
			buildRunResults.FailedSkippableSteps = append(buildRunResults.FailedSkippableSteps, stepResults)
			break
		case models.StepRunStatusCodeSkipped:
			log.Warnf("A previous step failed, and this step (%s) was not marked as IsAlwaysRun, skipped", name)
			buildRunResults.SkippedSteps = append(buildRunResults.SkippedSteps, stepResults)
			break
		case models.StepRunStatusCodeSkippedWithRunIf:
			log.Warn("The step's (" + name + ") Run-If expression evaluated to false - skipping")
			buildRunResults.SkippedSteps = append(buildRunResults.SkippedSteps, stepResults)
			break
		default:
			log.Error("Unkown result code")
			return
		}

		bitrise.PrintStepSummary(stepResults, isLastStep)
	}

	for idx, stepListItm := range workflow.Steps {
		stepStartTime = time.Now()
		isLastStep := isLastWorkflow && (idx == len(workflow.Steps)-1)

		if err := bitrise.SetBuildFailedEnv(buildRunResults.IsBuildFailed()); err != nil {
			log.Error("Failed to set Build Status envs")
		}

		compositeStepIDStr, workflowStep, err := models.GetStepIDStepDataPair(stepListItm)
		if err != nil {
			registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
			continue
		}
		stepIDData, err := models.CreateStepIDDataFromString(compositeStepIDStr, defaultStepLibSource)
		if err != nil {
			registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
			continue
		}
		stepVersionForInfoPrint := stepIDData.Version

		log.Debugf("[BITRISE_CLI] - Running Step: %#v", workflowStep)

		if err := bitrise.CleanupStepWorkDir(); err != nil {
			registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
			continue
		}

		stepDir := bitrise.BitriseWorkStepsDirPath
		stepYMLPth := path.Join(bitrise.BitriseWorkDirPath, "current_step.yml")

		if stepIDData.SteplibSource == "path" {
			log.Debugf("[BITRISE_CLI] - Local step found: (path:%s)", stepIDData.IDorURI)
			stepAbsLocalPth, err := pathutil.AbsPath(stepIDData.IDorURI)
			if err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			log.Debugln("stepAbsLocalPth:", stepAbsLocalPth, "|stepDir:", stepDir)

			if err := cmdex.CopyDir(stepAbsLocalPth, stepDir, true); err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			if err := cmdex.CopyFile(path.Join(stepAbsLocalPth, "step.yml"), stepYMLPth); err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			if len(stepIDData.IDorURI) > 20 {
				stepVersionForInfoPrint = fmt.Sprintf("path:...%s", stringutil.MaxLastChars(stepIDData.IDorURI, 17))
			} else {
				stepVersionForInfoPrint = fmt.Sprintf("path:%s", stepIDData.IDorURI)
			}
		} else if stepIDData.SteplibSource == "git" {
			log.Debugf("[BITRISE_CLI] - Remote step, with direct git uri: (uri:%s) (tag-or-branch:%s)", stepIDData.IDorURI, stepIDData.Version)
			if err := cmdex.GitCloneTagOrBranch(stepIDData.IDorURI, stepDir, stepIDData.Version); err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			if err := cmdex.CopyFile(path.Join(stepDir, "step.yml"), stepYMLPth); err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			stepVersionForInfoPrint = fmt.Sprintf("git:...%s", stringutil.MaxLastChars(stepIDData.IDorURI, 10))
			if stepIDData.Version != "" {
				stepVersionForInfoPrint = stepVersionForInfoPrint + "@" + stepIDData.Version
			}
		} else if stepIDData.SteplibSource == "_" {
			log.Debugf("[BITRISE_CLI] - Steplib independent step, with direct git uri: (uri:%s) (tag-or-branch:%s)", stepIDData.IDorURI, stepIDData.Version)

			// Steplib independent steps are completly defined in workflow
			stepYMLPth = ""
			if err := workflowStep.FillMissingDefaults(); err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			if err := cmdex.GitCloneTagOrBranch(stepIDData.IDorURI, stepDir, stepIDData.Version); err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			stepVersionForInfoPrint = "_"
			if stepIDData.Version != "" {
				if len(stepIDData.Version) > 20 {
					stepVersionForInfoPrint = stepVersionForInfoPrint + "@..." + stringutil.MaxLastChars(stepIDData.Version, 17)
				} else {
					stepVersionForInfoPrint = stepVersionForInfoPrint + "@" + stepIDData.Version
				}
			}
		} else if stepIDData.SteplibSource != "" {
			log.Debugf("[BITRISE_CLI] - Steplib (%s) step (id:%s) (version:%s) found, activating step", stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
			if err := bitrise.StepmanSetup(stepIDData.SteplibSource); err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			stepInfo, err := bitrise.StepmanStepInfo(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
			if err != nil {
				if buildRunResults.IsStepLibUpdated(stepIDData.SteplibSource) {
					registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
					continue
				}
				// May StepLib should be updated
				log.Info("Step info not found in StepLib (%s) -- Updating ...")
				if err := bitrise.StepmanUpdate(stepIDData.SteplibSource); err != nil {
					registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
					continue
				}
				buildRunResults.StepmanUpdates[stepIDData.SteplibSource]++
				stepInfo, err = bitrise.StepmanStepInfo(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
				if err != nil {
					registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
					continue
				}
			}

			stepVersionForInfoPrint = stepInfo.StepVersion

			if err := bitrise.StepmanActivate(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version, stepDir, stepYMLPth); err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			} else {
				log.Debugf("[BITRISE_CLI] - Step activated: (ID:%s) (version:%s)", stepIDData.IDorURI, stepIDData.Version)
			}
		} else {
			registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, fmt.Errorf("Invalid stepIDData: No SteplibSource or LocalPath defined (%v)", stepIDData), isLastStep)
			continue
		}

		mergedStep := workflowStep
		if stepYMLPth != "" {
			specStep, err := bitrise.ReadSpecStep(stepYMLPth)
			log.Debugf("Spec read from YML: %#v\n", specStep)
			if err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			mergedStep, err = models.MergeStepWith(specStep, workflowStep)
			if err != nil {
				registerStepListItemRunResults(stepListItm, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}
		}

		// Run step
		bitrise.PrintRunningStep(*mergedStep.Title, stepVersionForInfoPrint, idx)
		if mergedStep.RunIf != nil && *mergedStep.RunIf != "" {
			isRun, err := bitrise.EvaluateStepTemplateToBool(*mergedStep.RunIf, buildRunResults)
			if err != nil {
				registerStepRunResults(mergedStep, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}
			if !isRun {
				registerStepRunResults(mergedStep, models.StepRunStatusCodeSkippedWithRunIf, 0, err, isLastStep)
				continue
			}
		}
		outEnvironments := []envmanModels.EnvironmentItemModel{}

		isAlwaysRun := stepmanModels.DefaultIsAlwaysRun
		if mergedStep.IsAlwaysRun != nil {
			isAlwaysRun = *mergedStep.IsAlwaysRun
		} else {
			log.Warn("Step (%s) mergedStep.IsAlwaysRun is nil, should not!", stepIDData.IDorURI)
		}

		if buildRunResults.IsBuildFailed() && !isAlwaysRun {
			registerStepRunResults(mergedStep, models.StepRunStatusCodeSkipped, 0, err, isLastStep)
		} else {
			exit, out, err := runStep(mergedStep, stepIDData, stepDir, *environments)
			outEnvironments = out
			if err != nil {
				if *mergedStep.IsSkippable {
					registerStepRunResults(mergedStep, models.StepRunStatusCodeFailedSkippable, exit, err, isLastStep)
				} else {
					registerStepRunResults(mergedStep, models.StepRunStatusCodeFailed, exit, err, isLastStep)
				}
			} else {
				registerStepRunResults(mergedStep, models.StepRunStatusCodeSuccess, 0, nil, isLastStep)
				*environments = append(*environments, outEnvironments...)
			}
		}
	}

	return buildRunResults
}
Пример #10
0
// PrintRunningWorkflow ...
func PrintRunningWorkflow(title string) {
	fmt.Println()
	log.Infoln(colorstring.Blue("Switching to workflow:"), title)
	fmt.Println()
}
Пример #11
0
func triggerCheck(c *cli.Context) error {
	warnings := []string{}

	//
	// Expand cli.Context
	prGlobalFlag := c.GlobalBool(PRKey)

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

	pushBranch := c.String(PushBranchKey)
	prSourceBranch := c.String(PRSourceBranchKey)
	prTargetBranch := c.String(PRTargetBranchKey)

	bitriseConfigBase64Data := c.String(ConfigBase64Key)
	bitriseConfigPath := c.String(ConfigKey)
	deprecatedBitriseConfigPath := c.String(PathKey)
	if bitriseConfigPath == "" && deprecatedBitriseConfigPath != "" {
		warnings = append(warnings, "'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)

	format := c.String(OuputFormatKey)

	triggerParams, err := parseTriggerCheckParams(
		triggerPattern,
		pushBranch, prSourceBranch, prTargetBranch,
		format,
		bitriseConfigPath, bitriseConfigBase64Data,
		inventoryPath, inventoryBase64Data,
		jsonParams, jsonParamsBase64)
	if err != nil {
		registerFatal(fmt.Sprintf("Failed to parse trigger check params, err: %s", err), warnings, triggerParams.Format)
	}
	//

	// Inventory validation
	inventoryEnvironments, err := CreateInventoryFromCLIParams(triggerParams.InventoryBase64Data, triggerParams.InventoryPath)
	if err != nil {
		registerFatal(fmt.Sprintf("Failed to create inventory, err: %s", err), warnings, triggerParams.Format)
	}

	// Config validation
	bitriseConfig, warns, err := CreateBitriseConfigFromCLIParams(triggerParams.BitriseConfigBase64Data, triggerParams.BitriseConfigPath)
	warnings = append(warnings, warns...)
	if err != nil {
		registerFatal(fmt.Sprintf("Failed to create config, err: %s", err), warnings, triggerParams.Format)
	}

	// Format validation
	if triggerParams.Format == "" {
		triggerParams.Format = output.FormatRaw
	} else if !(triggerParams.Format == output.FormatRaw || triggerParams.Format == output.FormatJSON) {
		registerFatal(fmt.Sprintf("Invalid format: %s", triggerParams.Format), warnings, output.FormatJSON)
	}

	// Trigger filter validation
	if triggerParams.TriggerPattern == "" &&
		triggerParams.PushBranch == "" && triggerParams.PRSourceBranch == "" && triggerParams.PRTargetBranch == "" {
		registerFatal("No trigger pattern nor trigger params specified", warnings, triggerParams.Format)
	}
	//

	//
	// Main
	isPRMode, err := isPRMode(prGlobalFlag, inventoryEnvironments)
	if err != nil {
		registerFatal(fmt.Sprintf("Failed to check  PR mode, err: %s", err), warnings, triggerParams.Format)
	}

	workflowToRunID, err := getWorkflowIDByParamsInCompatibleMode(bitriseConfig.TriggerMap, triggerParams, isPRMode)
	if err != nil {
		registerFatal(err.Error(), warnings, triggerParams.Format)
	}

	switch triggerParams.Format {
	case output.FormatRaw:
		fmt.Printf("%s -> %s\n", triggerParams.TriggerPattern, colorstring.Blue(workflowToRunID))
		break
	case output.FormatJSON:
		triggerModel := map[string]string{
			"pattern":  triggerParams.TriggerPattern,
			"workflow": workflowToRunID,
		}
		bytes, err := json.Marshal(triggerModel)
		if err != nil {
			registerFatal(fmt.Sprintf("Failed to parse trigger model, err: %s", err), warnings, triggerParams.Format)
		}

		fmt.Println(string(bytes))
		break
	default:
		registerFatal(fmt.Sprintf("Invalid format: %s", triggerParams.Format), warnings, output.FormatJSON)
	}
	//

	return nil
}
Пример #12
0
func activateAndRunSteps(workflow models.WorkflowModel, defaultStepLibSource string, buildRunResults models.BuildRunResultsModel, environments *[]envmanModels.EnvironmentItemModel, isLastWorkflow bool) models.BuildRunResultsModel {
	log.Debugln("[BITRISE_CLI] - Activating and running steps")

	// ------------------------------------------
	// In function global variables - These are global for easy use in local register step run result methods.
	var stepStartTime time.Time

	// ------------------------------------------
	// In function method - Registration methods, for register step run results.
	registerStepRunResults := func(step stepmanModels.StepModel, stepInfoPtr stepmanModels.StepInfoModel,
		stepIdxPtr int, runIf string, resultCode, exitCode int, err error, isLastStep, printStepHeader bool) {

		if printStepHeader {
			bitrise.PrintRunningStepHeader(stepInfoPtr, step, stepIdxPtr)
		}

		stepInfoCopy := stepmanModels.StepInfoModel{
			ID:            stepInfoPtr.ID,
			Title:         stepInfoPtr.Title,
			Version:       stepInfoPtr.Version,
			Latest:        stepInfoPtr.Latest,
			SupportURL:    stepInfoPtr.SupportURL,
			SourceCodeURL: stepInfoPtr.SourceCodeURL,
			GlobalInfo:    stepInfoPtr.GlobalInfo,
		}

		stepResults := models.StepRunResultsModel{
			StepInfo: stepInfoCopy,
			Status:   resultCode,
			Idx:      buildRunResults.ResultsCount(),
			RunTime:  time.Now().Sub(stepStartTime),
			Error:    err,
			ExitCode: exitCode,
		}

		isExitStatusError := true
		if err != nil {
			isExitStatusError = errorutil.IsExitStatusError(err)
		}

		switch resultCode {
		case models.StepRunStatusCodeSuccess:
			buildRunResults.SuccessSteps = append(buildRunResults.SuccessSteps, stepResults)
			break
		case models.StepRunStatusCodeFailed:
			if !isExitStatusError {
				log.Errorf("Step (%s) failed, error: %s", stepInfoCopy.Title, err)
			}

			buildRunResults.FailedSteps = append(buildRunResults.FailedSteps, stepResults)
			break
		case models.StepRunStatusCodeFailedSkippable:
			if !isExitStatusError {
				log.Warnf("Step (%s) failed, but was marked as skippable, error: %s", stepInfoCopy.Title, err)
			} else {
				log.Warnf("Step (%s) failed, but was marked as skippable", stepInfoCopy.Title)
			}

			buildRunResults.FailedSkippableSteps = append(buildRunResults.FailedSkippableSteps, stepResults)
			break
		case models.StepRunStatusCodeSkipped:
			log.Warnf("A previous step failed, and this step (%s) was not marked as IsAlwaysRun, skipped", stepInfoCopy.Title)

			buildRunResults.SkippedSteps = append(buildRunResults.SkippedSteps, stepResults)
			break
		case models.StepRunStatusCodeSkippedWithRunIf:
			log.Warn("The step's (" + stepInfoCopy.Title + ") Run-If expression evaluated to false - skipping")
			if runIf != "" {
				log.Info("The Run-If expression was: ", colorstring.Blue(runIf))
			}

			buildRunResults.SkippedSteps = append(buildRunResults.SkippedSteps, stepResults)
			break
		default:
			log.Error("Unkown result code")
			return
		}

		bitrise.PrintRunningStepFooter(stepResults, isLastStep)
	}

	// ------------------------------------------
	// Main - Preparing & running the steps
	for idx, stepListItm := range workflow.Steps {
		// Per step variables
		stepStartTime = time.Now()
		isLastStep := isLastWorkflow && (idx == len(workflow.Steps)-1)
		stepInfoPtr := stepmanModels.StepInfoModel{}
		stepIdxPtr := idx

		// Per step cleanup
		if err := bitrise.SetBuildFailedEnv(buildRunResults.IsBuildFailed()); err != nil {
			log.Error("Failed to set Build Status envs")
		}

		if err := bitrise.CleanupStepWorkDir(); err != nil {
			registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
				"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
			continue
		}

		//
		// Preparing the step
		if err := tools.EnvmanInitAtPath(configs.InputEnvstorePath); err != nil {
			registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
				"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
			continue
		}

		if err := bitrise.ExportEnvironmentsList(*environments); err != nil {
			registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
				"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
			continue
		}

		// Get step id & version data
		compositeStepIDStr, workflowStep, err := models.GetStepIDStepDataPair(stepListItm)
		if err != nil {
			registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
				"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
			continue
		}
		stepInfoPtr.ID = compositeStepIDStr
		if workflowStep.Title != nil && *workflowStep.Title != "" {
			stepInfoPtr.Title = *workflowStep.Title
		} else {
			stepInfoPtr.Title = compositeStepIDStr
		}

		stepIDData, err := models.CreateStepIDDataFromString(compositeStepIDStr, defaultStepLibSource)
		if err != nil {
			registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
				"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
			continue
		}
		stepInfoPtr.ID = stepIDData.IDorURI
		if stepInfoPtr.Title == "" {
			stepInfoPtr.Title = stepIDData.IDorURI
		}
		stepInfoPtr.Version = stepIDData.Version
		stepInfoPtr.StepLib = stepIDData.SteplibSource

		//
		// Activating the step
		stepDir := configs.BitriseWorkStepsDirPath
		stepYMLPth := filepath.Join(configs.BitriseWorkDirPath, "current_step.yml")

		if stepIDData.SteplibSource == "path" {
			log.Debugf("[BITRISE_CLI] - Local step found: (path:%s)", stepIDData.IDorURI)
			stepAbsLocalPth, err := pathutil.AbsPath(stepIDData.IDorURI)
			if err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}

			log.Debugln("stepAbsLocalPth:", stepAbsLocalPth, "|stepDir:", stepDir)

			if err := cmdex.CopyDir(stepAbsLocalPth, stepDir, true); err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}

			if err := cmdex.CopyFile(filepath.Join(stepAbsLocalPth, "step.yml"), stepYMLPth); err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}
		} else if stepIDData.SteplibSource == "git" {
			log.Debugf("[BITRISE_CLI] - Remote step, with direct git uri: (uri:%s) (tag-or-branch:%s)", stepIDData.IDorURI, stepIDData.Version)
			if err := cmdex.GitCloneTagOrBranch(stepIDData.IDorURI, stepDir, stepIDData.Version); err != nil {
				if strings.HasPrefix(stepIDData.IDorURI, "git@") {
					fmt.Println(colorstring.Yellow(`Note: if the step's repository is an open source one,`))
					fmt.Println(colorstring.Yellow(`you should probably use a "https://..." git clone URL,`))
					fmt.Println(colorstring.Yellow(`instead of the "git@..." git clone URL which usually requires authentication`))
					fmt.Println(colorstring.Yellow(`even if the repository is open source!`))
				}
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}

			if err := cmdex.CopyFile(filepath.Join(stepDir, "step.yml"), stepYMLPth); err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}
		} else if stepIDData.SteplibSource == "_" {
			log.Debugf("[BITRISE_CLI] - Steplib independent step, with direct git uri: (uri:%s) (tag-or-branch:%s)", stepIDData.IDorURI, stepIDData.Version)

			// Steplib independent steps are completly defined in workflow
			stepYMLPth = ""
			if err := workflowStep.FillMissingDefaults(); err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}

			if err := cmdex.GitCloneTagOrBranch(stepIDData.IDorURI, stepDir, stepIDData.Version); err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}
		} else if stepIDData.SteplibSource != "" {
			log.Debugf("[BITRISE_CLI] - Steplib (%s) step (id:%s) (version:%s) found, activating step", stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
			if err := tools.StepmanSetup(stepIDData.SteplibSource); err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}

			isLatestVersionOfStep := (stepIDData.Version == "")
			if isLatestVersionOfStep && !buildRunResults.IsStepLibUpdated(stepIDData.SteplibSource) {
				log.Infof("Step uses latest version -- Updating StepLib ...")
				if err := tools.StepmanUpdate(stepIDData.SteplibSource); err != nil {
					log.Warnf("Step uses latest version, but failed to update StepLib, err: %s", err)
				} else {
					buildRunResults.StepmanUpdates[stepIDData.SteplibSource]++
				}
			}

			outStr, err := tools.StepmanJSONStepLibStepInfo(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
			if err != nil {
				if buildRunResults.IsStepLibUpdated(stepIDData.SteplibSource) {
					registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
						"", models.StepRunStatusCodeFailed, 1, fmt.Errorf("StepmanJSONStepLibStepInfo failed, err: %s", err), isLastStep, true)
					continue
				}
				// May StepLib should be updated
				log.Infof("Step info not found in StepLib (%s) -- Updating ...", stepIDData.SteplibSource)
				if err := tools.StepmanUpdate(stepIDData.SteplibSource); err != nil {
					registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
						"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
					continue
				}
				buildRunResults.StepmanUpdates[stepIDData.SteplibSource]++

				outStr, err = tools.StepmanJSONStepLibStepInfo(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
				if err != nil {
					registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
						"", models.StepRunStatusCodeFailed, 1, fmt.Errorf("StepmanJSONStepLibStepInfo failed, err: %s", err), isLastStep, true)
					continue
				}
			}

			stepInfo, err := stepmanModels.StepInfoModel{}.CreateFromJSON(outStr)
			if err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, fmt.Errorf("CreateFromJSON failed, err: %s", err), isLastStep, true)
				continue
			}

			stepInfoPtr.ID = stepInfo.ID
			if stepInfoPtr.Title == "" {
				stepInfoPtr.Title = stepInfo.ID
			}
			stepInfoPtr.Version = stepInfo.Version
			stepInfoPtr.Latest = stepInfo.Latest
			stepInfoPtr.GlobalInfo = stepInfo.GlobalInfo

			if err := tools.StepmanActivate(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version, stepDir, stepYMLPth); err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			} else {
				log.Debugf("[BITRISE_CLI] - Step activated: (ID:%s) (version:%s)", stepIDData.IDorURI, stepIDData.Version)
			}
		} else {
			registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
				"", models.StepRunStatusCodeFailed, 1, fmt.Errorf("Invalid stepIDData: No SteplibSource or LocalPath defined (%v)", stepIDData), isLastStep, true)
			continue
		}

		// Fill step info with default step info, if exist
		mergedStep := workflowStep
		if stepYMLPth != "" {
			specStep, err := bitrise.ReadSpecStep(stepYMLPth)
			log.Debugf("Spec read from YML: %#v\n", specStep)
			if err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}

			mergedStep, err = models.MergeStepWith(specStep, workflowStep)
			if err != nil {
				registerStepRunResults(stepmanModels.StepModel{}, stepInfoPtr, stepIdxPtr,
					"", models.StepRunStatusCodeFailed, 1, err, isLastStep, true)
				continue
			}
		}

		if mergedStep.SupportURL != nil {
			stepInfoPtr.SupportURL = *mergedStep.SupportURL
		}
		if mergedStep.SourceCodeURL != nil {
			stepInfoPtr.SourceCodeURL = *mergedStep.SourceCodeURL
		}

		//
		// Run step
		bitrise.PrintRunningStepHeader(stepInfoPtr, mergedStep, idx)
		if mergedStep.RunIf != nil && *mergedStep.RunIf != "" {
			outStr, err := tools.EnvmanJSONPrint(configs.InputEnvstorePath)
			if err != nil {
				registerStepRunResults(mergedStep, stepInfoPtr, stepIdxPtr,
					*mergedStep.RunIf, models.StepRunStatusCodeFailed, 1, fmt.Errorf("EnvmanJSONPrint failed, err: %s", err), isLastStep, false)
				continue
			}

			envList, err := envmanModels.NewEnvJSONList(outStr)
			if err != nil {
				registerStepRunResults(mergedStep, stepInfoPtr, stepIdxPtr,
					*mergedStep.RunIf, models.StepRunStatusCodeFailed, 1, fmt.Errorf("CreateFromJSON failed, err: %s", err), isLastStep, false)
				continue
			}

			isRun, err := bitrise.EvaluateTemplateToBool(*mergedStep.RunIf, configs.IsCIMode, configs.IsPullRequestMode, buildRunResults, envList)
			if err != nil {
				registerStepRunResults(mergedStep, stepInfoPtr, stepIdxPtr,
					*mergedStep.RunIf, models.StepRunStatusCodeFailed, 1, err, isLastStep, false)
				continue
			}
			if !isRun {
				registerStepRunResults(mergedStep, stepInfoPtr, stepIdxPtr,
					*mergedStep.RunIf, models.StepRunStatusCodeSkippedWithRunIf, 0, err, isLastStep, false)
				continue
			}
		}

		isAlwaysRun := stepmanModels.DefaultIsAlwaysRun
		if mergedStep.IsAlwaysRun != nil {
			isAlwaysRun = *mergedStep.IsAlwaysRun
		} else {
			log.Warn("Step (%s) mergedStep.IsAlwaysRun is nil, should not!", stepIDData.IDorURI)
		}

		if buildRunResults.IsBuildFailed() && !isAlwaysRun {
			registerStepRunResults(mergedStep, stepInfoPtr, stepIdxPtr,
				*mergedStep.RunIf, models.StepRunStatusCodeSkipped, 0, err, isLastStep, false)
		} else {
			exit, outEnvironments, err := runStep(mergedStep, stepIDData, stepDir, *environments, buildRunResults)
			*environments = append(*environments, outEnvironments...)
			if err != nil {
				if *mergedStep.IsSkippable {
					registerStepRunResults(mergedStep, stepInfoPtr, stepIdxPtr,
						*mergedStep.RunIf, models.StepRunStatusCodeFailedSkippable, exit, err, isLastStep, false)
				} else {
					registerStepRunResults(mergedStep, stepInfoPtr, stepIdxPtr,
						*mergedStep.RunIf, models.StepRunStatusCodeFailed, exit, err, isLastStep, false)
				}
			} else {
				registerStepRunResults(mergedStep, stepInfoPtr, stepIdxPtr,
					*mergedStep.RunIf, models.StepRunStatusCodeSuccess, 0, nil, isLastStep, false)
			}
		}
	}

	return buildRunResults
}
Пример #13
0
func activateAndRunSteps(workflow models.WorkflowModel, defaultStepLibSource string, buildRunResults models.BuildRunResultsModel, environments *[]envmanModels.EnvironmentItemModel, isLastWorkflow bool) models.BuildRunResultsModel {
	log.Debugln("[BITRISE_CLI] - Activating and running steps")

	// ------------------------------------------
	// In function global variables - These are global for easy use in local register step run result methods.
	var stepStartTime time.Time

	// Holds pointer to current step info, for easy usage in local register step run result methods.
	// The value is filled with the current running step info.
	var stepInfoPtr models.StepInfoModel

	// ------------------------------------------
	// In function method - Registration methods, for register step run results.
	registerStepRunResults := func(runIf string, resultCode, exitCode int, err error, isLastStep bool) {
		stepInfoCopy := models.StepInfoModel{
			ID:      stepInfoPtr.ID,
			Version: stepInfoPtr.Version,
			Latest:  stepInfoPtr.Latest,
		}

		stepResults := models.StepRunResultsModel{
			StepInfo: stepInfoCopy,
			Status:   resultCode,
			Idx:      buildRunResults.ResultsCount(),
			RunTime:  time.Now().Sub(stepStartTime),
			Error:    err,
			ExitCode: exitCode,
		}

		switch resultCode {
		case models.StepRunStatusCodeSuccess:
			buildRunResults.SuccessSteps = append(buildRunResults.SuccessSteps, stepResults)
			break
		case models.StepRunStatusCodeFailed:
			log.Errorf("Step (%s) failed, error: (%v)", stepInfoCopy.ID, err)
			buildRunResults.FailedSteps = append(buildRunResults.FailedSteps, stepResults)
			break
		case models.StepRunStatusCodeFailedSkippable:
			log.Warnf("Step (%s) failed, but was marked as skippable, error: (%v)", stepInfoCopy.ID, err)
			buildRunResults.FailedSkippableSteps = append(buildRunResults.FailedSkippableSteps, stepResults)
			break
		case models.StepRunStatusCodeSkipped:
			log.Warnf("A previous step failed, and this step (%s) was not marked as IsAlwaysRun, skipped", stepInfoCopy.ID)
			buildRunResults.SkippedSteps = append(buildRunResults.SkippedSteps, stepResults)
			break
		case models.StepRunStatusCodeSkippedWithRunIf:
			log.Warn("The step's (" + stepInfoCopy.ID + ") Run-If expression evaluated to false - skipping")
			if runIf != "" {
				log.Info("The Run-If expression was: ", colorstring.Blue(runIf))
			}
			buildRunResults.SkippedSteps = append(buildRunResults.SkippedSteps, stepResults)
			break
		default:
			log.Error("Unkown result code")
			return
		}

		bitrise.PrintStepSummary(stepResults, isLastStep)
	}

	// ------------------------------------------
	// Main - Preparing & running the steps
	for idx, stepListItm := range workflow.Steps {
		// Per step variables
		stepStartTime = time.Now()
		isLastStep := isLastWorkflow && (idx == len(workflow.Steps)-1)
		stepInfoPtr = models.StepInfoModel{}

		// Per step cleanup
		if err := bitrise.SetBuildFailedEnv(buildRunResults.IsBuildFailed()); err != nil {
			log.Error("Failed to set Build Status envs")
		}

		if err := bitrise.CleanupStepWorkDir(); err != nil {
			registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
			continue
		}

		//
		// Preparing the step

		// Get step id & version data
		compositeStepIDStr, workflowStep, err := models.GetStepIDStepDataPair(stepListItm)
		stepInfoPtr.ID = compositeStepIDStr
		if workflowStep.Title != nil && *workflowStep.Title != "" {
			stepInfoPtr.ID = *workflowStep.Title
		}
		if err != nil {
			registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
			continue
		}

		stepIDData, err := models.CreateStepIDDataFromString(compositeStepIDStr, defaultStepLibSource)
		stepInfoPtr.ID = stepIDData.IDorURI
		if workflowStep.Title != nil && *workflowStep.Title != "" {
			stepInfoPtr.ID = *workflowStep.Title
		}
		stepInfoPtr.Version = stepIDData.Version
		if err != nil {
			registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
			continue
		}

		stepDir := bitrise.BitriseWorkStepsDirPath
		stepYMLPth := path.Join(bitrise.BitriseWorkDirPath, "current_step.yml")

		// Activating the step
		if stepIDData.SteplibSource == "path" {
			log.Debugf("[BITRISE_CLI] - Local step found: (path:%s)", stepIDData.IDorURI)
			stepAbsLocalPth, err := pathutil.AbsPath(stepIDData.IDorURI)
			if err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			log.Debugln("stepAbsLocalPth:", stepAbsLocalPth, "|stepDir:", stepDir)

			if err := cmdex.CopyDir(stepAbsLocalPth, stepDir, true); err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			if err := cmdex.CopyFile(path.Join(stepAbsLocalPth, "step.yml"), stepYMLPth); err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			if len(stepIDData.IDorURI) > 20 {
				stepInfoPtr.Version = fmt.Sprintf("path:...%s", stringutil.MaxLastChars(stepIDData.IDorURI, 17))
			} else {
				stepInfoPtr.Version = fmt.Sprintf("path:%s", stepIDData.IDorURI)
			}
		} else if stepIDData.SteplibSource == "git" {
			log.Debugf("[BITRISE_CLI] - Remote step, with direct git uri: (uri:%s) (tag-or-branch:%s)", stepIDData.IDorURI, stepIDData.Version)
			if err := cmdex.GitCloneTagOrBranch(stepIDData.IDorURI, stepDir, stepIDData.Version); err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			if err := cmdex.CopyFile(path.Join(stepDir, "step.yml"), stepYMLPth); err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			stepInfoPtr.Version = fmt.Sprintf("git:...%s", stringutil.MaxLastChars(stepIDData.IDorURI, 10))
			if stepIDData.Version != "" {
				stepInfoPtr.Version = stepInfoPtr.Version + "@" + stepIDData.Version
			}
		} else if stepIDData.SteplibSource == "_" {
			log.Debugf("[BITRISE_CLI] - Steplib independent step, with direct git uri: (uri:%s) (tag-or-branch:%s)", stepIDData.IDorURI, stepIDData.Version)

			// Steplib independent steps are completly defined in workflow
			stepYMLPth = ""
			if err := workflowStep.FillMissingDefaults(); err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			if err := cmdex.GitCloneTagOrBranch(stepIDData.IDorURI, stepDir, stepIDData.Version); err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			stepInfoPtr.Version = "_"
			if stepIDData.Version != "" {
				if len(stepIDData.Version) > 20 {
					stepInfoPtr.Version = stepInfoPtr.Version + "@..." + stringutil.MaxLastChars(stepIDData.Version, 17)
				} else {
					stepInfoPtr.Version = stepInfoPtr.Version + "@" + stepIDData.Version
				}
			}
		} else if stepIDData.SteplibSource != "" {
			log.Debugf("[BITRISE_CLI] - Steplib (%s) step (id:%s) (version:%s) found, activating step", stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
			if err := bitrise.StepmanSetup(stepIDData.SteplibSource); err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			stepInfo, err := bitrise.StepmanStepInfo(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
			if err != nil {
				if buildRunResults.IsStepLibUpdated(stepIDData.SteplibSource) {
					registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
					continue
				}
				// May StepLib should be updated
				log.Info("Step info not found in StepLib (%s) -- Updating ...")
				if err := bitrise.StepmanUpdate(stepIDData.SteplibSource); err != nil {
					registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
					continue
				}
				buildRunResults.StepmanUpdates[stepIDData.SteplibSource]++
				stepInfo, err = bitrise.StepmanStepInfo(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version)
				if err != nil {
					registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
					continue
				}
			}

			stepInfoPtr.Version = stepInfo.Version
			stepInfoPtr.Latest = stepInfo.Latest

			if err := bitrise.StepmanActivate(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version, stepDir, stepYMLPth); err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			} else {
				log.Debugf("[BITRISE_CLI] - Step activated: (ID:%s) (version:%s)", stepIDData.IDorURI, stepIDData.Version)
			}
		} else {
			registerStepRunResults("", models.StepRunStatusCodeFailed, 1, fmt.Errorf("Invalid stepIDData: No SteplibSource or LocalPath defined (%v)", stepIDData), isLastStep)
			continue
		}

		// Fill step info with default step info, if exist
		mergedStep := workflowStep
		if stepYMLPth != "" {
			specStep, err := bitrise.ReadSpecStep(stepYMLPth)
			log.Debugf("Spec read from YML: %#v\n", specStep)
			if err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}

			mergedStep, err = models.MergeStepWith(specStep, workflowStep)
			if err != nil {
				registerStepRunResults("", models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}
		}

		// Run step
		bitrise.PrintRunningStep(stepInfoPtr, idx)
		if mergedStep.RunIf != nil && *mergedStep.RunIf != "" {
			isRun, err := bitrise.EvaluateStepTemplateToBool(*mergedStep.RunIf, buildRunResults)
			if err != nil {
				registerStepRunResults(*mergedStep.RunIf, models.StepRunStatusCodeFailed, 1, err, isLastStep)
				continue
			}
			if !isRun {
				registerStepRunResults(*mergedStep.RunIf, models.StepRunStatusCodeSkippedWithRunIf, 0, err, isLastStep)
				continue
			}
		}
		outEnvironments := []envmanModels.EnvironmentItemModel{}

		isAlwaysRun := stepmanModels.DefaultIsAlwaysRun
		if mergedStep.IsAlwaysRun != nil {
			isAlwaysRun = *mergedStep.IsAlwaysRun
		} else {
			log.Warn("Step (%s) mergedStep.IsAlwaysRun is nil, should not!", stepIDData.IDorURI)
		}

		if buildRunResults.IsBuildFailed() && !isAlwaysRun {
			registerStepRunResults(*mergedStep.RunIf, models.StepRunStatusCodeSkipped, 0, err, isLastStep)
		} else {
			exit, out, err := runStep(mergedStep, stepIDData, stepDir, *environments)
			outEnvironments = out
			if err != nil {
				if *mergedStep.IsSkippable {
					registerStepRunResults(*mergedStep.RunIf, models.StepRunStatusCodeFailedSkippable, exit, err, isLastStep)
				} else {
					registerStepRunResults(*mergedStep.RunIf, models.StepRunStatusCodeFailed, exit, err, isLastStep)
				}
			} else {
				registerStepRunResults(*mergedStep.RunIf, models.StepRunStatusCodeSuccess, 0, nil, isLastStep)
				*environments = append(*environments, outEnvironments...)
			}
		}
	}

	return buildRunResults
}
Пример #14
0
func collectAndExportProvisioningProfiles(codeSigningSettings common.CodeSigningSettings,
	absExportOutputDirPath string) (provprofile.ProvisioningProfileFileInfoModels, error) {

	provProfileFileInfos := []provprofile.ProvisioningProfileFileInfoModel{}

	fmt.Println()
	log.Println(colorstring.Green("Searching for required Provisioning Profiles"), "...")
	fmt.Println()

	provProfileUUIDLookupMap := map[string]provprofile.ProvisioningProfileFileInfoModel{}
	for _, aProvProfile := range codeSigningSettings.ProvProfiles {
		log.Infof(" * "+colorstring.Blue("Searching for required Provisioning Profile")+": %s (UUID: %s)", aProvProfile.Title, aProvProfile.UUID)
		provProfileFileInfo, err := provprofile.FindProvProfileByUUID(aProvProfile.UUID)
		if err != nil {
			return provProfileFileInfos, fmt.Errorf("Failed to find Provisioning Profile: %s", err)
		}
		log.Infof("   File found at: %s", provProfileFileInfo.Path)

		provProfileUUIDLookupMap[provProfileFileInfo.ProvisioningProfileInfo.UUID] = provProfileFileInfo
	}

	fmt.Println()
	log.Println(colorstring.Green("Searching for additinal, Distribution Provisioning Profiles"), "...")
	fmt.Println()
	for _, aAppBundleID := range codeSigningSettings.AppIDs {
		bundleOrAppIDPattern := common.BundleIDFromAppID(aAppBundleID)
		if bundleOrAppIDPattern == "" {
			// no bundle ID found in the app id
			bundleOrAppIDPattern = aAppBundleID
		} else {
			// bundle ID found, make it a glob pattern
			bundleOrAppIDPattern = "*." + bundleOrAppIDPattern
		}
		log.Infof(" * "+colorstring.Blue("Searching for Provisioning Profiles with App ID pattern")+": %s", bundleOrAppIDPattern)
		provProfileFileInfos, err := provprofile.FindProvProfilesByAppID(bundleOrAppIDPattern)
		if err != nil {
			return provProfileFileInfos, fmt.Errorf("Error during Provisioning Profile search: %s", err)
		}
		if len(provProfileFileInfos) < 1 {
			log.Warn("   No Provisioning Profile found for this Bundle ID")
			continue
		}
		log.Infof("   Found matching Provisioning Profile count: %d", len(provProfileFileInfos))

		for _, aProvProfileFileInfo := range provProfileFileInfos {
			provProfileUUIDLookupMap[aProvProfileFileInfo.ProvisioningProfileInfo.UUID] = aProvProfileFileInfo
		}
	}

	fmt.Println()
	log.Println(colorstring.Green("Exporting Provisioning Profiles"), "...")
	fmt.Println()
	for _, aProvProfFileInfo := range provProfileUUIDLookupMap {
		provProfileFileInfos = append(provProfileFileInfos, aProvProfFileInfo)
	}
	if err := exportProvisioningProfiles(provProfileFileInfos, absExportOutputDirPath); err != nil {
		return provProfileFileInfos, fmt.Errorf("Failed to export the Provisioning Profile into the export directory: %s", err)
	}

	return provProfileFileInfos, nil
}
Пример #15
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
}
Пример #16
0
// GuideTextForFinish ...
func GuideTextForFinish() string {
	guide := "Everything is ready! The only remaning thing is to " + colorstring.Blue("create a Pull Request") + `.
	`
	return guide
}
Пример #17
0
func collectAndExportIdentities(codeSigningSettings common.CodeSigningSettings, additionalTeamIDs []string,
	absExportOutputDirPath string) error {

	fmt.Println()
	log.Println("Collecting the required Identities (Certificates) for a base Xcode Archive ...")
	fmt.Println()

	identitiesWithKeychainRefs := []osxkeychain.IdentityWithRefModel{}
	defer osxkeychain.ReleaseIdentityWithRefList(identitiesWithKeychainRefs)

	for _, aIdentity := range codeSigningSettings.Identities {
		log.Infof(" * "+colorstring.Blue("Searching for Identity")+": %s", aIdentity.Title)
		validIdentityRefs, err := osxkeychain.FindAndValidateIdentity(aIdentity.Title, true)
		if err != nil {
			return fmt.Errorf("Failed to export, error: %s", err)
		}

		if len(validIdentityRefs) < 1 {
			return errors.New("Identity not found in the keychain, or it was invalid (expired)!")
		}
		if len(validIdentityRefs) > 1 {
			log.Warning(colorstring.Yellow("Multiple matching Identities found in Keychain! Most likely you have duplicated identities in separate Keychains, e.g. one in System.keychain and one in your Login.keychain, or you have revoked versions of the Certificate."))
		} else {
			log.Infoln("   " + colorstring.Green("Found - OK"))
		}

		identitiesWithKeychainRefs = append(identitiesWithKeychainRefs, validIdentityRefs...)
	}

	fmt.Println()
	log.Println("Collecting additional identities, for Distribution builds ...")
	fmt.Println()

	totalTeamIDs := append(codeSigningSettings.TeamIDs, additionalTeamIDs...)
	for _, aTeamID := range sliceutil.UniqueStringSlice(totalTeamIDs) {
		log.Infof(" * "+colorstring.Blue("Searching for Identities with Team ID")+": %s", aTeamID)
		validIdentityRefs, err := osxkeychain.FindAndValidateIdentity(fmt.Sprintf("(%s)", aTeamID), false)
		if err != nil {
			return fmt.Errorf("Failed to export, error: %s", err)
		}

		if len(validIdentityRefs) < 1 {
			log.Infoln("No valid identity found for this Team ID")
		}
		log.Infoln("   "+colorstring.Green("Found identities count")+":", len(validIdentityRefs))

		identitiesWithKeychainRefs = append(identitiesWithKeychainRefs, validIdentityRefs...)
	}

	fmt.Println()
	log.Println(colorstring.Green("Exporting the Identities") + " (Certificates):")
	fmt.Println()

	identityKechainRefs := osxkeychain.CreateEmptyCFTypeRefSlice()
	for _, aIdentityWithRefItm := range identitiesWithKeychainRefs {
		fmt.Println(" * "+colorstring.Blue("Identity")+":", aIdentityWithRefItm.Label)
		identityKechainRefs = append(identityKechainRefs, aIdentityWithRefItm.KeychainRef)
	}

	fmt.Println()
	if isAskForPassword {
		log.Infoln(colorstring.Blue("Exporting from Keychain"))
		log.Infoln(colorstring.Yellow(" You'll be asked to provide a Passphrase for the .p12 file!"))
	} else {
		log.Infoln(colorstring.Blue("Exporting from Keychain") + ", " + colorstring.Yellow("using empty Passphrase") + " ...")
		log.Info(" This means that " + colorstring.Yellow("if you want to import the file the passphrase at import should be left empty") + ",")
		log.Info(" you don't have to type in anything, just leave the passphrase input empty.")
	}
	fmt.Println()
	log.Info(colorstring.Blue("You'll most likely see popups") + " (one for each Identity) from Keychain,")
	log.Info(colorstring.Yellow(" you will have to accept (Allow)") + " those to be able to export the Identities!")
	fmt.Println()

	if err := osxkeychain.ExportFromKeychain(identityKechainRefs, filepath.Join(absExportOutputDirPath, "Identities.p12"), isAskForPassword); err != nil {
		return fmt.Errorf("Failed to export from Keychain: %s", err)
	}

	return nil
}
Пример #18
0
// Info ...
func Info(format string, v ...interface{}) {
	message := fmt.Sprintf(format, v...)
	fmt.Println(colorstring.Blue(message))
}