Exemplo n.º 1
0
// GetStepFromNewSteplib ...
func GetStepFromNewSteplib(stepID, stepLibGitURI string) (stepmanModels.StepModel, string, error) {
	// Activate step - get step.yml
	tempStepCloneDirPath, err := pathutil.NormalizedOSTempDirPath("step_clone")
	if err != nil {
		return stepmanModels.StepModel{}, "", err
	}
	tempStepYMLDirPath, err := pathutil.NormalizedOSTempDirPath("step_yml")
	if err != nil {
		return stepmanModels.StepModel{}, "", err
	}
	tempStepYMLFilePath := path.Join(tempStepYMLDirPath, "step.yml")

	// Stepman
	if err := bitrise.StepmanSetup(stepLibGitURI); err != nil {
		return stepmanModels.StepModel{}, "", err
	}

	stepInfo, err := bitrise.StepmanStepInfo(stepLibGitURI, stepID, "")
	if err != nil {
		// May StepLib should be updated
		log.Info("Step info not found in StepLib (%s) -- Updating ...")
		if err := bitrise.StepmanUpdate(stepLibGitURI); err != nil {
			return stepmanModels.StepModel{}, "", err
		}
		stepInfo, err = bitrise.StepmanStepInfo(stepLibGitURI, stepID, "")
		if err != nil {
			return stepmanModels.StepModel{}, "", err
		}
	}

	stepVersion := stepInfo.StepVersion

	if err := bitrise.StepmanActivate(stepLibGitURI, stepID, "", tempStepCloneDirPath, tempStepYMLFilePath); err != nil {
		return stepmanModels.StepModel{}, "", err
	}

	specStep, err := ReadSpecStep(tempStepYMLFilePath)
	if err != nil {
		return stepmanModels.StepModel{}, "", err
	}

	// Cleanup
	if err := cmdex.RemoveDir(tempStepCloneDirPath); err != nil {
		return stepmanModels.StepModel{}, "", errors.New(fmt.Sprint("Failed to remove step clone dir: ", err))
	}
	if err := cmdex.RemoveDir(tempStepYMLDirPath); err != nil {
		return stepmanModels.StepModel{}, "", errors.New(fmt.Sprint("Failed to remove step clone dir: ", err))
	}

	return specStep, stepVersion, nil
}
Exemplo n.º 2
0
func TestClonePluginSrc(t *testing.T) {
	t.Log("example plugin - latest version")
	{
		pluginSource := examplePluginGitURL
		versionTag := ""
		destinationDir, err := pathutil.NormalizedOSTempDirPath("TestClonePluginSrc")
		require.NoError(t, err)

		exist, err := pathutil.IsPathExists(destinationDir)
		require.NoError(t, err)
		if exist {
			err := os.RemoveAll(destinationDir)
			require.NoError(t, err)
		}

		version, hash, err := clonePluginSrc(pluginSource, versionTag, destinationDir)
		require.NoError(t, err)
		require.NotNil(t, version)
		require.NotEmpty(t, hash)

		exist, err = pathutil.IsPathExists(destinationDir)
		require.NoError(t, err)
		require.Equal(t, true, exist)
	}

	t.Log("example plugin - 0.9.0 version")
	{
		pluginSource := examplePluginGitURL
		versionTag := "0.9.0"
		destinationDir, err := pathutil.NormalizedOSTempDirPath("TestClonePluginSrc")
		require.NoError(t, err)

		exist, err := pathutil.IsPathExists(destinationDir)
		require.NoError(t, err)
		if exist {
			err := os.RemoveAll(destinationDir)
			require.NoError(t, err)
		}

		version, hash, err := clonePluginSrc(pluginSource, versionTag, destinationDir)
		require.NoError(t, err)
		require.NotNil(t, version)
		require.Equal(t, "0.9.0", version.String())
		require.NotEmpty(t, hash)

		exist, err = pathutil.IsPathExists(destinationDir)
		require.NoError(t, err)
		require.Equal(t, true, exist)
	}
}
Exemplo n.º 3
0
func TestDownloadPluginBin(t *testing.T) {
	t.Log("example plugin bin - ")
	{
		pluginBinURL := analyticsPluginBinURL
		destinationDir, err := pathutil.NormalizedOSTempDirPath("TestDownloadPluginBin")
		require.NoError(t, err)

		exist, err := pathutil.IsPathExists(destinationDir)
		require.NoError(t, err)
		if exist {
			err := os.RemoveAll(destinationDir)
			require.NoError(t, err)
		}

		require.NoError(t, os.MkdirAll(destinationDir, 0777))

		destinationPth := filepath.Join(destinationDir, "example")

		require.NoError(t, downloadPluginBin(pluginBinURL, destinationPth))

		exist, err = pathutil.IsPathExists(destinationPth)
		require.NoError(t, err)
		require.Equal(t, true, exist)
	}
}
Exemplo n.º 4
0
func saveRawOutputToLogFile(rawXcodebuildOutput string, isRunSuccess bool) error {
	tmpDir, err := pathutil.NormalizedOSTempDirPath("xcodebuild-output")
	if err != nil {
		return fmt.Errorf("Failed to create temp dir, error: %s", err)
	}
	logFileName := "raw-xcodebuild-output.log"
	logPth := filepath.Join(tmpDir, logFileName)
	if err := fileutil.WriteStringToFile(logPth, rawXcodebuildOutput); err != nil {
		return fmt.Errorf("Failed to write xcodebuild output to file, error: %s", err)
	}

	if !isRunSuccess {
		deployDir := os.Getenv("BITRISE_DEPLOY_DIR")
		if deployDir == "" {
			return errors.New("No BITRISE_DEPLOY_DIR found")
		}
		deployPth := filepath.Join(deployDir, logFileName)

		if err := cmdex.CopyFile(logPth, deployPth); err != nil {
			return fmt.Errorf("Failed to copy xcodebuild output log file from (%s) to (%s), error: %s", logPth, deployPth, err)
		}
		logPth = deployPth
	}

	if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_RAW_TEST_RESULT_TEXT_PATH", logPth); err != nil {
		log.Warn("Failed to export: BITRISE_XCODE_RAW_TEST_RESULT_TEXT_PATH, error: %s", err)
	}
	return nil
}
Exemplo n.º 5
0
func auditStepModelBeforeSharePullRequest(step models.StepModel, stepID, version string) error {
	if err := step.Audit(); err != nil {
		return fmt.Errorf("Failed to audit step infos, error: %s", err)
	}

	pth, err := pathutil.NormalizedOSTempDirPath(stepID + version)
	if err != nil {
		return fmt.Errorf("Failed to create a temporary directory for the step's audit, error: %s", err)
	}

	if step.Source == nil {
		return fmt.Errorf("Missing Source porperty")
	}

	err = retry.Times(2).Wait(3 * time.Second).Try(func(attempt uint) error {
		return cmdex.GitCloneTag(step.Source.Git, pth, version)
	})
	if err != nil {
		return fmt.Errorf("Failed to git-clone the step (url: %s) version (%s), error: %s",
			step.Source.Git, version, err)
	}

	latestCommit, err := cmdex.GitGetLatestCommitHashOnHead(pth)
	if err != nil {
		return fmt.Errorf("Failed to get git-latest-commit-hash, error: %s", err)
	}
	if latestCommit != step.Source.Commit {
		return fmt.Errorf("Step commit hash (%s) should be the  latest commit hash (%s) on git tag", step.Source.Commit, latestCommit)
	}

	return nil
}
Exemplo n.º 6
0
func initBitriseWorkPaths() error {
	bitriseWorkDirPath, err := pathutil.NormalizedOSTempDirPath("bitrise")
	if err != nil {
		return err
	}
	if exist, err := pathutil.IsPathExists(bitriseWorkDirPath); err != nil {
		return err
	} else if !exist {
		if err := os.MkdirAll(bitriseWorkDirPath, 0777); err != nil {
			return err
		}
	}
	BitriseWorkDirPath = bitriseWorkDirPath

	bitriseWorkStepsDirPath, err := filepath.Abs(filepath.Join(BitriseWorkDirPath, "step_src"))
	if err != nil {
		return err
	}
	if exist, err := pathutil.IsPathExists(bitriseWorkStepsDirPath); err != nil {
		return err
	} else if !exist {
		if err := os.MkdirAll(bitriseWorkStepsDirPath, 0777); err != nil {
			return err
		}
	}
	BitriseWorkStepsDirPath = bitriseWorkStepsDirPath

	return nil
}
Exemplo n.º 7
0
func goBuildInIsolation(packageName, srcPath, outputBinPath string) error {
	log.Debugf("=> Installing package (%s) to path (%s) ...", packageName, srcPath)
	workspaceRootPath, err := pathutil.NormalizedOSTempDirPath("bitrise-go-toolkit")
	if err != nil {
		return fmt.Errorf("Failed to create root directory of isolated workspace, error: %s", err)
	}
	log.Debugln("=> Using sandboxed workspace:", workspaceRootPath)

	// origGOPATH := os.Getenv("GOPATH")
	// if origGOPATH == "" {
	// 	return fmt.Errorf("You don't have a GOPATH environment - please set it; GOPATH/bin will be symlinked")
	// }

	// log.Debugln("=> Symlink GOPATH/bin into sandbox ...")
	// if err := gows.CreateGopathBinSymlink(origGOPATH, workspaceRootPath); err != nil {
	// 	return fmt.Errorf("Failed to create GOPATH/bin symlink, error: %s", err)
	// }
	// log.Debugln("   [DONE]")

	fullPackageWorkspacePath := filepath.Join(workspaceRootPath, "src", packageName)
	log.Debugf("=> Creating Symlink: (%s) -> (%s)", srcPath, fullPackageWorkspacePath)
	if err := gows.CreateOrUpdateSymlink(srcPath, fullPackageWorkspacePath); err != nil {
		return fmt.Errorf("Failed to create Project->Workspace symlink, error: %s", err)
	}
	log.Debugf(" [DONE] Symlink is in place")

	log.Debugln("=> Building package " + packageName + " ...")
	{
		isInstallRequired, _, goConfig, err := selectGoConfiguration()
		if err != nil {
			return fmt.Errorf("Failed to select an appropriate Go installation for compiling the step, error: %s", err)
		}
		if isInstallRequired {
			return fmt.Errorf("Failed to select an appropriate Go installation for compiling the step, error: %s",
				"Found Go version is older than required. Please run 'bitrise setup' to check and install the required version")
		}

		cmd := gows.CreateCommand(workspaceRootPath, workspaceRootPath,
			goConfig.GoBinaryPath, "build", "-o", outputBinPath, packageName)
		cmd.Env = append(cmd.Env, "GOROOT="+goConfig.GOROOT)
		if err := cmd.Run(); err != nil {
			return fmt.Errorf("Failed to install package, error: %s", err)
		}
	}
	log.Debugln("   [DONE] Package successfully installed")

	log.Debugln("=> Delete isolated workspace ...")
	{
		if err := os.RemoveAll(workspaceRootPath); err != nil {
			return fmt.Errorf("Failed to delete temporary isolated workspace, error: %s", err)
		}
	}
	log.Debugln("   [DONE]")

	return nil
}
// WritePlistToTmpFile ...
func WritePlistToTmpFile(options map[string]interface{}) (string, error) {
	tmpDir, err := pathutil.NormalizedOSTempDirPath("output")
	if err != nil {
		return "", fmt.Errorf("failed to create temp dir, error: %s", err)
	}
	pth := filepath.Join(tmpDir, "exportOptions.plist")

	if err := WritePlistToFile(options, pth); err != nil {
		return "", fmt.Errorf("failed to write to file options, error: %s", err)
	}

	return pth, nil
}
Exemplo n.º 9
0
func TestEnvmanJSONPrint(t *testing.T) {
	// Initialized envstore -- Err should empty, output filled
	testDirPth, err := pathutil.NormalizedOSTempDirPath("test_env_store")
	require.Equal(t, nil, err)

	envstorePth := path.Join(testDirPth, "envstore.yml")

	require.Equal(t, nil, EnvmanInitAtPath(envstorePth))

	outStr, err := EnvmanJSONPrint(envstorePth)
	require.Equal(t, nil, err)
	require.NotEqual(t, "", outStr)

	// Not initialized envstore -- Err should filled, output empty
	testDirPth, err = pathutil.NormalizedOSTempDirPath("test_env_store")
	require.Equal(t, nil, err)

	envstorePth = path.Join("test_env_store", "envstore.yml")

	outStr, err = EnvmanJSONPrint(envstorePth)
	require.NotEqual(t, nil, err)
	require.Equal(t, "", outStr)
}
Exemplo n.º 10
0
// InitPaths ...
func InitPaths() error {
	if err := initBitriseWorkPaths(); err != nil {
		return fmt.Errorf("Failed to init bitrise paths: %s", err)
	}

	inputEnvstorePath, err := filepath.Abs(path.Join(BitriseWorkDirPath, "input_envstore.yml"))
	if err != nil {
		return fmt.Errorf("Failed to set envstore path: %s", err)
	}
	InputEnvstorePath = inputEnvstorePath

	outputEnvstorePath, err := filepath.Abs(path.Join(BitriseWorkDirPath, "output_envstore.yml"))
	if err != nil {
		return fmt.Errorf("Failed to set envstore path: %s", err)
	}
	OutputEnvstorePath = outputEnvstorePath

	formoutPath, err := filepath.Abs(path.Join(BitriseWorkDirPath, "formatted_output.md"))
	if err != nil {
		return fmt.Errorf("Failed to set formatted output path: %s", err)
	}
	FormattedOutputPath = formoutPath

	currentDir, err := filepath.Abs("./")
	if err != nil {
		return fmt.Errorf("Failed to set current dir: %s", err)
	}
	CurrentDir = currentDir

	// BITRISE_SOURCE_DIR
	if os.Getenv(BitriseSourceDirEnvKey) == "" {
		if err := os.Setenv(BitriseSourceDirEnvKey, currentDir); err != nil {
			return fmt.Errorf("Failed to set BITRISE_SOURCE_DIR: %s", err)
		}
	}

	// BITRISE_DEPLOY_DIR
	if os.Getenv(BitriseDeployDirEnvKey) == "" {
		deployDir, err := pathutil.NormalizedOSTempDirPath("deploy")
		if err != nil {
			return fmt.Errorf("Failed to set deploy dir: %s", err)
		}

		if err := os.Setenv(BitriseDeployDirEnvKey, deployDir); err != nil {
			return fmt.Errorf("Failed to set BITRISE_DEPLOY_DIR: %s", err)
		}
	}

	return nil
}
Exemplo n.º 11
0
// ExportOutputDirAsZip ...
func ExportOutputDirAsZip(sourceDirPth, destinationPth, envKey string) error {
	tmpDir, err := pathutil.NormalizedOSTempDirPath("__export_tmp_dir__")
	if err != nil {
		return err
	}

	base := filepath.Base(sourceDirPth)
	tmpZipFilePth := filepath.Join(tmpDir, base+".zip")

	if err := zip(sourceDirPth, tmpZipFilePth); err != nil {
		return err
	}

	return ExportOutputFile(tmpZipFilePth, destinationPth, envKey)
}
Exemplo n.º 12
0
func TestNewHelper(t *testing.T) {
	t.Log("it fails if destinationDir empty")
	{
		helper, err := NewHelper("", "https://github.com/bitrise-samples/git-clone-test.git", false)
		require.Error(t, err)
		require.Equal(t, "", helper.destinationDir)
		require.Equal(t, "", helper.remoteURI)
	}

	t.Log("it fails if remote URI empty")
	{
		helper, err := NewHelper("./", "", false)
		require.Error(t, err)
		require.Equal(t, "", helper.destinationDir)
		require.Equal(t, "", helper.remoteURI)
	}

	t.Log("it fails if remote URI empty")
	{
		helper, err := NewHelper("./", "", false)
		require.Error(t, err)
		require.Equal(t, "", helper.destinationDir)
		require.Equal(t, "", helper.remoteURI)
	}

	t.Log("it creates destination dir if not exist")
	{
		tmpDir, err := pathutil.NormalizedOSTempDirPath("__test__")
		require.NoError(t, err)

		destinationDir := filepath.Join(tmpDir, "dst")
		exist, err := pathutil.IsDirExists(destinationDir)
		require.NoError(t, err)
		require.Equal(t, false, exist)

		helper, err := NewHelper(destinationDir, "https://github.com/bitrise-samples/git-clone-test.git", false)
		require.NoError(t, err)
		require.Equal(t, destinationDir, helper.destinationDir)
		require.Equal(t, "https://github.com/bitrise-samples/git-clone-test.git", helper.remoteURI)

		exist, err = pathutil.IsDirExists(destinationDir)
		require.NoError(t, err)
		require.Equal(t, true, exist)

		require.NoError(t, os.RemoveAll(tmpDir))
	}
}
Exemplo n.º 13
0
func Test_ValidateTestJSON(t *testing.T) {
	tmpDir, err := pathutil.NormalizedOSTempDirPath("__validate_test__")
	require.NoError(t, err)
	defer func() {
		require.NoError(t, os.RemoveAll(tmpDir))
	}()

	t.Log("valid bitrise.yml")
	{
		cmd := cmdex.NewCommand(binPath(), "validate", "-c", "trigger_params_test_bitrise.yml", "--format", "json")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.NoError(t, err)
		require.Equal(t, "{\"data\":{\"config\":{\"is_valid\":true}}}", out)
	}

	t.Log("valid - warning test - `-p` flag is deprecated")
	{
		cmd := cmdex.NewCommand(binPath(), "validate", "-p", "trigger_params_test_bitrise.yml", "--format", "json")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.NoError(t, err)
		require.Equal(t, "{\"data\":{\"config\":{\"is_valid\":true}},\"warnings\":[\"'path' key is deprecated, use 'config' instead!\"]}", out)
	}

	t.Log("valid - invalid workflow id")
	{
		configPth := filepath.Join(tmpDir, "bitrise.yml")
		require.NoError(t, fileutil.WriteStringToFile(configPth, invalidWorkflowIDBitriseYML))

		cmd := cmdex.NewCommand(binPath(), "validate", "-c", configPth, "--format", "json")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.NoError(t, err)
		expected := "{\"data\":{\"config\":{\"is_valid\":true,\"warnings\":[\"invalid workflow ID (invalid:id): doesn't conform to: [A-Za-z0-9-_.]\"]}}}"
		require.Equal(t, expected, out)
	}

	t.Log("invalid - empty bitrise.yml")
	{
		configPth := filepath.Join(tmpDir, "bitrise.yml")
		require.NoError(t, fileutil.WriteStringToFile(configPth, emptyBitriseYML))

		cmd := cmdex.NewCommand(binPath(), "validate", "-c", configPth, "--format", "json")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.Error(t, err, out)
		expected := fmt.Sprintf("{\"data\":{\"config\":{\"is_valid\":false,\"error\":\"Config (path:%s) is not valid: empty config\"}}}", configPth)
		require.Equal(t, expected, out)
	}
}
Exemplo n.º 14
0
func Test_ValidateTest(t *testing.T) {
	tmpDir, err := pathutil.NormalizedOSTempDirPath("__validate_test__")
	require.NoError(t, err)
	defer func() {
		require.NoError(t, os.RemoveAll(tmpDir))
	}()

	t.Log("valid bitrise.yml")
	{
		cmd := cmdex.NewCommand(binPath(), "validate", "-c", "trigger_params_test_bitrise.yml")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.NoError(t, err)
		require.Equal(t, "Config is valid: \x1b[32;1mtrue\x1b[0m", out)
	}

	t.Log("valid - warning test - `-p` flag is deprecated")
	{
		cmd := cmdex.NewCommand(binPath(), "validate", "-p", "trigger_params_test_bitrise.yml")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.NoError(t, err)
		require.Equal(t, "Config is valid: \x1b[32;1mtrue\x1b[0m\nWarning(s):\n- 'path' key is deprecated, use 'config' instead!", out)
	}

	t.Log("valid - invalid workflow id")
	{
		configPth := filepath.Join(tmpDir, "bitrise.yml")
		require.NoError(t, fileutil.WriteStringToFile(configPth, invalidWorkflowIDBitriseYML))

		cmd := cmdex.NewCommand(binPath(), "validate", "-c", configPth)
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.NoError(t, err)
		expected := "Config is valid: \x1b[32;1mtrue\x1b[0m\nWarning(s):\n- invalid workflow ID (invalid:id): doesn't conform to: [A-Za-z0-9-_.]"
		require.Equal(t, expected, out)
	}

	t.Log("invalid - empty bitrise.yml")
	{
		configPth := filepath.Join(tmpDir, "bitrise.yml")
		require.NoError(t, fileutil.WriteStringToFile(configPth, emptyBitriseYML))

		cmd := cmdex.NewCommand(binPath(), "validate", "-c", configPth)
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.Error(t, err, out)
		expected := fmt.Sprintf("Config is valid: \x1b[31;1mfalse\x1b[0m\nError: \x1b[31;1mConfig (path:%s) is not valid: empty config\x1b[0m", configPth)
		require.Equal(t, expected, out)
	}
}
Exemplo n.º 15
0
func TestSetupForVersionChecks(t *testing.T) {
	fakeHomePth, err := pathutil.NormalizedOSTempDirPath("_FAKE_HOME")
	require.Equal(t, nil, err)
	originalHome := os.Getenv("HOME")

	defer func() {
		require.Equal(t, nil, os.Setenv("HOME", originalHome))
		require.Equal(t, nil, os.RemoveAll(fakeHomePth))
	}()

	require.Equal(t, nil, os.Setenv("HOME", fakeHomePth))

	require.Equal(t, false, CheckIsSetupWasDoneForVersion("0.9.7"))

	require.Equal(t, nil, SaveSetupSuccessForVersion("0.9.7"))

	require.Equal(t, true, CheckIsSetupWasDoneForVersion("0.9.7"))

	require.Equal(t, false, CheckIsSetupWasDoneForVersion("0.9.8"))
}
Exemplo n.º 16
0
func TestGetConfigs(t *testing.T) {
	// fake home, to save the configs into
	fakeHomePth, err := pathutil.NormalizedOSTempDirPath("_FAKE_HOME")
	t.Logf("fakeHomePth: %s", fakeHomePth)
	require.NoError(t, err)
	originalHome := os.Getenv("HOME")
	defer func() {
		require.NoError(t, os.Setenv("HOME", originalHome))
		require.NoError(t, os.RemoveAll(fakeHomePth))
	}()
	require.Equal(t, nil, os.Setenv("HOME", fakeHomePth))

	configPth := getEnvmanConfigsFilePath()
	t.Logf("configPth: %s", configPth)

	// --- TESTING

	baseConf, err := GetConfigs()
	t.Logf("baseConf: %#v", baseConf)
	require.NoError(t, err)
	require.Equal(t, defaultEnvBytesLimitInKB, baseConf.EnvBytesLimitInKB)
	require.Equal(t, defaultEnvListBytesLimitInKB, baseConf.EnvListBytesLimitInKB)

	// modify it
	baseConf.EnvBytesLimitInKB = 123
	baseConf.EnvListBytesLimitInKB = 321

	// save to file
	require.NoError(t, saveConfigs(baseConf))

	// read it back
	configs, err := GetConfigs()
	t.Logf("configs: %#v", configs)
	require.NoError(t, err)
	require.Equal(t, configs, baseConf)
	require.Equal(t, 123, configs.EnvBytesLimitInKB)
	require.Equal(t, 321, configs.EnvListBytesLimitInKB)

	// delete the tmp config file
	require.NoError(t, os.Remove(configPth))
}
Exemplo n.º 17
0
// DownloadAndUnZIP ...
func DownloadAndUnZIP(url, pth string) error {
	tmpDir, err := pathutil.NormalizedOSTempDirPath("")
	if err != nil {
		return err
	}
	srcFilePath := tmpDir + "/target.zip"
	srcFile, err := os.Create(srcFilePath)
	if err != nil {
		return err
	}
	defer func() {
		if err := srcFile.Close(); err != nil {
			log.Fatal("Failed to close srcFile:", err)
		}
		if err := os.Remove(srcFilePath); err != nil {
			log.Fatal("Failed to remove srcFile:", err)
		}
	}()

	response, err := http.Get(url)
	if err != nil {
		return err
	}
	defer func() {
		if err := response.Body.Close(); err != nil {
			log.Fatal("Failed to close response body:", err)
		}
	}()

	if response.StatusCode != http.StatusOK {
		errorMsg := "Failed to download target from: " + url
		return errors.New(errorMsg)
	}

	if _, err := io.Copy(srcFile, response.Body); err != nil {
		return err
	}

	return UnZIP(srcFilePath, pth)
}
Exemplo n.º 18
0
func Test_SecretValidateTestJSON(t *testing.T) {
	tmpDir, err := pathutil.NormalizedOSTempDirPath("__validate_test__")
	require.NoError(t, err)
	defer func() {
		require.NoError(t, os.RemoveAll(tmpDir))
	}()

	t.Log("valid secret")
	{
		cmd := cmdex.NewCommand(binPath(), "validate", "-i", "global_flag_test_secrets.yml", "--format", "json")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.NoError(t, err)
		require.Equal(t, "{\"data\":{\"secrets\":{\"is_valid\":true}}}", out)
	}

	t.Log("invalid - empty config")
	{
		secretsPth := filepath.Join(tmpDir, "secrets.yml")
		require.NoError(t, fileutil.WriteStringToFile(secretsPth, emptySecret))

		cmd := cmdex.NewCommand(binPath(), "validate", "-i", secretsPth, "--format", "json")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.Error(t, err, out)
		expected := "{\"data\":{\"secrets\":{\"is_valid\":false,\"error\":\"empty config\"}}}"
		require.Equal(t, expected, out)
	}

	t.Log("invalid - invalid secret model")
	{
		secretsPth := filepath.Join(tmpDir, "secrets.yml")
		require.NoError(t, fileutil.WriteStringToFile(secretsPth, invalidSecret))

		cmd := cmdex.NewCommand(binPath(), "validate", "-i", secretsPth, "--format", "json")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.Error(t, err, out)
		expected := "{\"data\":{\"secrets\":{\"is_valid\":false,\"error\":\"Invalid invetory format: yaml: unmarshal errors:\\n  line 1: cannot unmarshal !!seq into models.EnvsYMLModel\"}}}"
		require.Equal(t, expected, out)
	}
}
Exemplo n.º 19
0
func Test_SecretValidateTest(t *testing.T) {
	tmpDir, err := pathutil.NormalizedOSTempDirPath("__validate_test__")
	require.NoError(t, err)
	defer func() {
		require.NoError(t, os.RemoveAll(tmpDir))
	}()

	t.Log("valid secret")
	{
		cmd := cmdex.NewCommand(binPath(), "validate", "-i", "global_flag_test_secrets.yml")
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.NoError(t, err)
		require.Equal(t, "Secret is valid: \x1b[32;1mtrue\x1b[0m", out)
	}

	t.Log("invalid - empty secret")
	{
		secretsPth := filepath.Join(tmpDir, "secrets.yml")
		require.NoError(t, fileutil.WriteStringToFile(secretsPth, emptySecret))

		cmd := cmdex.NewCommand(binPath(), "validate", "-i", secretsPth)
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.Error(t, err, out)
		expected := "Secret is valid: \x1b[31;1mfalse\x1b[0m\nError: \x1b[31;1mempty config\x1b[0m"
		require.Equal(t, expected, out)
	}

	t.Log("invalid - invalid secret model")
	{
		secretsPth := filepath.Join(tmpDir, "secrets.yml")
		require.NoError(t, fileutil.WriteStringToFile(secretsPth, invalidSecret))

		cmd := cmdex.NewCommand(binPath(), "validate", "-i", secretsPth)
		out, err := cmd.RunAndReturnTrimmedCombinedOutput()
		require.Error(t, err, out)
		expected := "Secret is valid: \x1b[31;1mfalse\x1b[0m\nError: \x1b[31;1mInvalid invetory format: yaml: unmarshal errors:\n  line 1: cannot unmarshal !!seq into models.EnvsYMLModel\x1b[0m"
		require.Equal(t, expected, out)
	}
}
Exemplo n.º 20
0
func auditStepModelBeforeSharePullRequest(step models.StepModel, stepID, version string) error {
	if err := step.Audit(); err != nil {
		return err
	}

	pth, err := pathutil.NormalizedOSTempDirPath(stepID + version)
	if err != nil {
		return err
	}
	if err := cmdex.GitCloneTag(step.Source.Git, pth, version); err != nil {
		return err
	}
	latestCommit, err := cmdex.GitGetLatestCommitHashOnHead(pth)
	if err != nil {
		return err
	}
	if latestCommit != step.Source.Commit {
		return fmt.Errorf("Step commit hash (%s) should be the  latest commit hash (%s) on git tag", step.Source.Commit, latestCommit)
	}

	return nil
}
Exemplo n.º 21
0
// InstallFromURL ...
func InstallFromURL(toolBinName, downloadURL string) error {
	if len(toolBinName) < 1 {
		return fmt.Errorf("no Tool (bin) Name provided! URL was: %s", downloadURL)
	}

	tmpDir, err := pathutil.NormalizedOSTempDirPath("__tmp_download_dest__")
	if err != nil {
		return fmt.Errorf("failed to create tmp dir for download destination")
	}
	tmpDestinationPth := filepath.Join(tmpDir, toolBinName)

	if err := DownloadFile(downloadURL, tmpDestinationPth); err != nil {
		return fmt.Errorf("failed to download, error: %s", err)
	}

	bitriseToolsDirPath := configs.GetBitriseToolsDirPath()
	destinationPth := filepath.Join(bitriseToolsDirPath, toolBinName)

	if exist, err := pathutil.IsPathExists(destinationPth); err != nil {
		return fmt.Errorf("failed to check if file exist (%s), error: %s", destinationPth, err)
	} else if exist {
		if err := os.Remove(destinationPth); err != nil {
			return fmt.Errorf("failed to remove file (%s), error: %s", destinationPth, err)
		}
	}

	if err := os.Rename(tmpDestinationPth, destinationPth); err != nil {
		return fmt.Errorf("failed to copy (%s) to (%s), error: %s", tmpDestinationPth, destinationPth, err)
	}

	if err := os.Chmod(destinationPth, 0755); err != nil {
		return fmt.Errorf("failed to make file (%s) executable, error: %s", destinationPth, err)
	}

	return nil
}
func main() {
	configs := createConfigsModelFromEnvs()

	fmt.Println()
	configs.print()

	if err := configs.validate(); err != nil {
		fmt.Println()
		log.Error("Issue with input: %s", err)

		os.Exit(1)
	}

	//
	// Create client
	fmt.Println()
	log.Info("Authenticateing")

	jwtConfig := new(jwt.Config)

	if configs.JSONKeyPath != "" {
		jsonKeyPth := ""

		if strings.HasPrefix(configs.JSONKeyPath, "file://") {
			jsonKeyPth = strings.TrimPrefix(configs.JSONKeyPath, "file://")
		} else {
			tmpDir, err := pathutil.NormalizedOSTempDirPath("__google-play-deploy__")
			if err != nil {
				log.Error("Failed to create tmp dir, error: %s", err)
				os.Exit(1)
			}

			jsonKeyPth = filepath.Join(tmpDir, "key.json")

			if err := downloadFile(configs.JSONKeyPath, jsonKeyPth); err != nil {
				log.Error("Failed to download json key file, error: %s", err)
				os.Exit(1)
			}
		}

		authConfig, err := jwtConfigFromJSONKeyFile(jsonKeyPth)
		if err != nil {
			log.Error("Failed to create auth config from json key file, error: %s", err)
			os.Exit(1)
		}
		jwtConfig = authConfig
	} else {
		p12KeyPath := ""

		if strings.HasPrefix(configs.P12KeyPath, "file://") {
			p12KeyPath = strings.TrimPrefix(configs.P12KeyPath, "file://")
		} else {
			tmpDir, err := pathutil.NormalizedOSTempDirPath("__google-play-deploy__")
			if err != nil {
				log.Error("Failed to create tmp dir, error: %s", err)
				os.Exit(1)
			}

			p12KeyPath = filepath.Join(tmpDir, "key.p12")

			if err := downloadFile(configs.P12KeyPath, p12KeyPath); err != nil {
				log.Error("Failed to download p12 key file, error: %s", err)
				os.Exit(1)
			}
		}

		authConfig, err := jwtConfigFromP12KeyFile(p12KeyPath, configs.ServiceAccountEmail)
		if err != nil {
			log.Error("Failed to create auth config from p12 key file, error: %s", err)
			os.Exit(1)
		}
		jwtConfig = authConfig
	}

	client := jwtConfig.Client(oauth2.NoContext)
	service, err := androidpublisher.New(client)
	if err != nil {
		log.Error("Failed to create publisher service, error: %s", err)
		os.Exit(1)
	}

	log.Done("Authenticated client created")
	// ---

	//
	// Create insert edit
	fmt.Println()
	log.Info("Create new edit")

	editsService := androidpublisher.NewEditsService(service)

	editsInsertCall := editsService.Insert(configs.PackageName, nil)

	appEdit, err := editsInsertCall.Do()
	if err != nil {
		log.Error("Failed to perform edit insert call, error: %s", err)
		os.Exit(1)
	}

	log.Detail(" editID: %s", appEdit.Id)
	// ---

	//
	// Upload APKs
	fmt.Println()
	log.Info("Upload apks")

	versionCodes := []int64{}
	apkPaths := strings.Split(configs.ApkPath, "|")
	for _, apkPath := range apkPaths {
		apkFile, err := os.Open(apkPath)
		if err != nil {
			log.Error("Failed to read apk (%s), error: %s", apkPath, err)
			os.Exit(1)
		}

		editsApksService := androidpublisher.NewEditsApksService(service)

		editsApksUloadCall := editsApksService.Upload(configs.PackageName, appEdit.Id)
		editsApksUloadCall.Media(apkFile, googleapi.ContentType("application/vnd.android.package-archive"))

		apk, err := editsApksUloadCall.Do()
		if err != nil {
			log.Error("Failed to upload apk, error: %s", err)
			os.Exit(1)
		}

		log.Detail(" uploaded apk version: %d", apk.VersionCode)
		versionCodes = append(versionCodes, apk.VersionCode)
	}
	// ---

	//
	// Update track
	fmt.Println()
	log.Info("Update track")

	editsTracksService := androidpublisher.NewEditsTracksService(service)

	newTrack := androidpublisher.Track{
		Track:        configs.Track,
		VersionCodes: versionCodes,
	}

	if configs.Track == "rollout" {
		userFraction, err := strconv.ParseFloat(configs.UserFraction, 64)
		if err != nil {
			log.Error("Failed to parse user fraction, error: %s", err)
			os.Exit(1)
		}
		newTrack.UserFraction = userFraction
	}

	editsTracksUpdateCall := editsTracksService.Update(configs.PackageName, appEdit.Id, configs.Track, &newTrack)
	track, err := editsTracksUpdateCall.Do()
	if err != nil {
		log.Error("Failed to update track, error: %s", err)
		os.Exit(1)
	}

	log.Detail(" updated track: %s", track.Track)
	log.Detail(" assigned apk versions: %v", track.VersionCodes)
	// ---

	//
	// Update listing
	if configs.WhatsnewsDir != "" {
		fmt.Println()
		log.Info("Update listing")

		recentChangesMap, err := readLocalisedRecentChanges(configs.WhatsnewsDir)
		if err != nil {
			log.Error("Failed to read whatsnews, error: %s", err)
			os.Exit(1)
		}

		editsApklistingsService := androidpublisher.NewEditsApklistingsService(service)

		for _, versionCode := range versionCodes {
			log.Detail(" updating recent changes for version: %d", versionCode)

			for language, recentChanges := range recentChangesMap {
				newApkListing := androidpublisher.ApkListing{
					Language:      language,
					RecentChanges: recentChanges,
				}

				editsApkListingsCall := editsApklistingsService.Update(configs.PackageName, appEdit.Id, versionCode, language, &newApkListing)
				apkListing, err := editsApkListingsCall.Do()
				if err != nil {
					log.Error("Failed to update listing, error: %s", err)
					os.Exit(1)
				}

				log.Detail(" - language: %s", apkListing.Language)
			}
		}
	}
	// ---

	//
	// Validate edit
	fmt.Println()
	log.Info("Validating edit")

	editsValidateCall := editsService.Validate(configs.PackageName, appEdit.Id)
	if _, err := editsValidateCall.Do(); err != nil {
		log.Error("Failed to validate edit, error: %s", err)
		os.Exit(1)
	}

	log.Done("Edit is valid")
	// ---

	//
	// Commit edit
	fmt.Println()
	log.Info("Committing edit")

	editsCommitCall := editsService.Commit(configs.PackageName, appEdit.Id)
	if _, err := editsCommitCall.Do(); err != nil {
		log.Error("Failed to commit edit, error: %s", err)
		os.Exit(1)
	}

	log.Done("Edit committed")
	// ---
}
Exemplo n.º 23
0
func main() {
	configs := createConfigsModelFromEnvs()

	fmt.Println()
	configs.print()

	if err := configs.validate(); err != nil {
		log.Error("Issue with input: %s", err)
		os.Exit(1)
	}

	nugetPth := "/Library/Frameworks/Mono.framework/Versions/Current/bin/nuget"
	nugetRestoreCmdArgs := []string{nugetPth}

	if configs.NugetVersion == "latest" {
		fmt.Println()
		log.Info("Updating Nuget to latest version...")
		// "sudo $nuget update -self"
		cmdArgs := []string{"sudo", nugetPth, "update", "-self"}
		cmd, err := cmdex.NewCommandFromSlice(cmdArgs)
		if err != nil {
			log.Error("Failed to create command from args (%v), error: %s", cmdArgs, err)
			os.Exit(1)
		}

		cmd.SetStdout(os.Stdout)
		cmd.SetStderr(os.Stderr)

		log.Done("$ %s", cmdex.PrintableCommandArgs(false, cmdArgs))

		if err := cmd.Run(); err != nil {
			log.Error("Failed to update nuget, error: %s", err)
			os.Exit(1)
		}
	} else if configs.NugetVersion != "" {
		fmt.Println()
		log.Info("Downloading Nuget %s version...", configs.NugetVersion)
		tmpDir, err := pathutil.NormalizedOSTempDirPath("__nuget__")
		if err != nil {
			log.Error("Failed to create tmp dir, error: %s", err)
			os.Exit(1)
		}

		downloadPth := filepath.Join(tmpDir, "nuget.exe")

		// https://dist.nuget.org/win-x86-commandline/v3.3.0/nuget.exe
		nugetURL := fmt.Sprintf("https://dist.nuget.org/win-x86-commandline/v%s/nuget.exe", configs.NugetVersion)

		log.Detail("Download URL: %s", nugetURL)

		if err := DownloadFile(nugetURL, downloadPth); err != nil {
			log.Warn("Download failed, error: %s", err)

			// https://dist.nuget.org/win-x86-commandline/v3.4.4/NuGet.exe
			nugetURL = fmt.Sprintf("https://dist.nuget.org/win-x86-commandline/v%s/NuGet.exe", configs.NugetVersion)

			log.Detail("Retry download URl: %s", nugetURL)

			if err := DownloadFile(nugetURL, downloadPth); err != nil {
				log.Error("Failed to download nuget, error: %s", err)
				os.Exit(1)
			}
		}

		nugetRestoreCmdArgs = []string{constants.MonoPath, downloadPth}
	}

	fmt.Println()
	log.Info("Restoring Nuget packages...")

	nugetRestoreCmdArgs = append(nugetRestoreCmdArgs, "restore", configs.XamarinSolution)

	if err := retry.Times(1).Try(func(attempt uint) error {
		if attempt > 0 {
			log.Warn("Attempt %d failed, retrying...", attempt)
		}

		log.Done("$ %s", cmdex.PrintableCommandArgs(false, nugetRestoreCmdArgs))

		cmd, err := cmdex.NewCommandFromSlice(nugetRestoreCmdArgs)
		if err != nil {
			log.Error("Failed to create Nuget command, error: %s", err)
			os.Exit(1)
		}

		cmd.SetStdout(os.Stdout)
		cmd.SetStderr(os.Stderr)

		if err := cmd.Run(); err != nil {
			log.Error("Restore failed, error: %s", err)
			return err
		}
		return nil
	}); err != nil {
		log.Error("Nuget restore failed, error: %s", err)
		os.Exit(1)
	}
}
Exemplo n.º 24
0
func create(c *cli.Context) error {
	toolMode := c.Bool(ToolMode)

	share, err := ReadShareSteplibFromFile()
	if err != nil {
		log.Error(err)
		log.Fatalln("You have to start sharing with `stepman share start`, or you can read instructions with `stepman share`")
	}

	// Input validation
	tag := c.String(TagKey)
	if tag == "" {
		log.Fatalln("No Step tag specified")
	}

	gitURI := c.String(GitKey)
	if gitURI == "" {
		log.Fatalln("No Step url specified")
	}

	stepID := c.String(StepIDKEy)
	if stepID == "" {
		stepID = getStepIDFromGit(gitURI)
	}
	if stepID == "" {
		log.Fatalln("No Step id specified")
	}
	r := regexp.MustCompile(`[a-z0-9-]+`)
	if find := r.FindString(stepID); find != stepID {
		log.Fatalln("StepID doesn't conforms to: [a-z0-9-]")
	}

	route, found := stepman.ReadRoute(share.Collection)
	if !found {
		log.Fatalf("No route found for collectionURI (%s)", share.Collection)
	}
	stepDirInSteplib := stepman.GetStepCollectionDirPath(route, stepID, tag)
	stepYMLPathInSteplib := path.Join(stepDirInSteplib, "step.yml")
	if exist, err := pathutil.IsPathExists(stepYMLPathInSteplib); err != nil {
		log.Fatalf("Failed to check step.yml path in steplib, err: %s", err)
	} else if exist {
		log.Warnf("Step already exist in path: %s.", stepDirInSteplib)
		if val, err := goinp.AskForBool("Would you like to overwrite local version of Step?"); err != nil {
			log.Fatalf("Failed to get bool, err: %s", err)
		} else {
			if !val {
				log.Errorln("Unfortunately we can't continue with sharing without an overwrite exist step.yml.")
				log.Fatalln("Please finish your changes, run this command again and allow it to overwrite the exist step.yml!")
			}
		}
	}

	// Clone Step to tmp dir
	tmp, err := pathutil.NormalizedOSTempDirPath("")
	if err != nil {
		log.Fatalf("Failed to get temp directory, err: %s", err)
	}

	log.Infof("Cloning Step from (%s) with tag (%s) to temporary path (%s)", gitURI, tag, tmp)
	if err := cmdex.GitCloneTag(gitURI, tmp, tag); err != nil {
		log.Fatalf("Git clone failed, err: %s", err)
	}

	// Update step.yml
	tmpStepYMLPath := path.Join(tmp, "step.yml")
	bytes, err := fileutil.ReadBytesFromFile(tmpStepYMLPath)
	if err != nil {
		log.Fatalf("Failed to read Step from file, err: %s", err)
	}
	var stepModel models.StepModel
	if err := yaml.Unmarshal(bytes, &stepModel); err != nil {
		log.Fatalf("Failed to unmarchal Step, err: %s", err)
	}

	commit, err := cmdex.GitGetCommitHashOfHEAD(tmp)
	if err != nil {
		log.Fatalf("Failed to get commit hash, err: %s", err)
	}
	stepModel.Source = &models.StepSourceModel{
		Git:    gitURI,
		Commit: commit,
	}
	stepModel.PublishedAt = pointers.NewTimePtr(time.Now())

	// Validate step-yml
	if err := stepModel.Audit(); err != nil {
		log.Fatalf("Failed to validate Step, err: %s", err)
	}
	for _, input := range stepModel.Inputs {
		key, value, err := input.GetKeyValuePair()
		if err != nil {
			log.Fatalf("Failed to get Step input key-value pair, err: %s", err)
		}

		options, err := input.GetOptions()
		if err != nil {
			log.Fatalf("Failed to get Step input (%s) options, err: %s", key, err)
		}

		if len(options.ValueOptions) > 0 && value == "" {
			log.Warn("Step input with 'value_options', should contain default value!")
			log.Fatalf("Missing default value for Step input (%s).", key)
		}
	}
	if strings.Contains(*stepModel.Summary, "\n") {
		log.Warningln("Step summary should be one line!")
	}
	if utf8.RuneCountInString(*stepModel.Summary) > maxSummaryLength {
		log.Warningf("Step summary should contains maximum (%d) characters, actual: (%d)!", maxSummaryLength, utf8.RuneCountInString(*stepModel.Summary))
	}

	// Copy step.yml to steplib
	share.StepID = stepID
	share.StepTag = tag
	if err := WriteShareSteplibToFile(share); err != nil {
		log.Fatalf("Failed to save share steplib to file, err: %s", err)
	}

	log.Info("Step dir in collection:", stepDirInSteplib)
	if exist, err := pathutil.IsPathExists(stepDirInSteplib); err != nil {
		log.Fatalf("Failed to check path (%s), err: %s", stepDirInSteplib, err)
	} else if !exist {
		if err := os.MkdirAll(stepDirInSteplib, 0777); err != nil {
			log.Fatalf("Failed to create path (%s), err: %s", stepDirInSteplib, err)
		}
	}

	log.Infof("Checkout branch: %s", share.ShareBranchName())
	collectionDir := stepman.GetCollectionBaseDirPath(route)
	if err := cmdex.GitCheckout(collectionDir, share.ShareBranchName()); err != nil {
		if err := cmdex.GitCreateAndCheckoutBranch(collectionDir, share.ShareBranchName()); err != nil {
			log.Fatalf("Git failed to create and checkout branch, err: %s", err)
		}
	}

	stepBytes, err := yaml.Marshal(stepModel)
	if err != nil {
		log.Fatalf("Failed to marcshal Step model, err: %s", err)
	}
	if err := fileutil.WriteBytesToFile(stepYMLPathInSteplib, stepBytes); err != nil {
		log.Fatalf("Failed to write Step to file, err: %s", err)
	}

	// Update spec.json
	if err := stepman.ReGenerateStepSpec(route); err != nil {
		log.Fatalf("Failed to re-create steplib, err: %s", err)
	}

	printFinishCreate(share, stepDirInSteplib, toolMode)

	return nil
}
Exemplo n.º 25
0
func runPlugin(plugin Plugin, args []string, pluginInput PluginInput) error {
	if !configs.IsCIMode && configs.CheckIsPluginUpdateCheckRequired() {
		// Check for new version
		log.Infof("Checking for plugin (%s) new version...", plugin.Name)

		if newVersion, err := CheckForNewVersion(plugin); err != nil {
			log.Warnf("")
			log.Warnf("Failed to check for plugin (%s) new version, error: %s", plugin.Name, err)
		} else if newVersion != "" {
			log.Warnf("")
			log.Warnf("New version (%s) of plugin (%s) available", newVersion, plugin.Name)

			route, found, err := ReadPluginRoute(plugin.Name)
			if err != nil {
				return err
			}
			if !found {
				return fmt.Errorf("no route found for already loaded plugin (%s)", plugin.Name)
			}

			route.LatestAvailableVersion = newVersion

			if err := AddPluginRoute(route); err != nil {
				return fmt.Errorf("failed to register available plugin (%s) update (%s), error: %s", plugin.Name, newVersion, err)
			}
		} else {
			log.Debugf("No new version of plugin (%s) available", plugin.Name)
		}

		if err := configs.SavePluginUpdateCheck(); err != nil {
			return err
		}

		fmt.Println()
	} else {
		route, found, err := ReadPluginRoute(plugin.Name)
		if err != nil {
			return err
		}
		if !found {
			return fmt.Errorf("no route found for already loaded plugin (%s)", plugin.Name)
		}

		if route.LatestAvailableVersion != "" {
			log.Warnf("")
			log.Warnf("New version (%s) of plugin (%s) available", route.LatestAvailableVersion, plugin.Name)
		}
	}

	// Append common data to plugin iputs
	bitriseVersion, err := version.BitriseCliVersion()
	if err != nil {
		return err
	}
	pluginInput[pluginInputBitriseVersionKey] = bitriseVersion.String()
	pluginInput[pluginInputDataDirKey] = GetPluginDataDir(plugin.Name)

	// Prepare plugin envstore
	pluginWorkDir, err := pathutil.NormalizedOSTempDirPath("plugin-work-dir")
	if err != nil {
		return err
	}
	defer func() {
		if err := os.RemoveAll(pluginWorkDir); err != nil {
			log.Warnf("Failed to remove path (%s)", pluginWorkDir)
		}
	}()

	pluginEnvstorePath := filepath.Join(pluginWorkDir, "envstore.yml")

	if err := tools.EnvmanInitAtPath(pluginEnvstorePath); err != nil {
		return err
	}

	if err := tools.EnvmanAdd(pluginEnvstorePath, configs.EnvstorePathEnvKey, pluginEnvstorePath, false, false); err != nil {
		return err
	}

	log.Debugf("plugin evstore path (%s)", pluginEnvstorePath)

	// Add plugin inputs
	for key, value := range pluginInput {
		if err := tools.EnvmanAdd(pluginEnvstorePath, key, value, false, false); err != nil {
			return err
		}
	}

	// Run plugin executable
	pluginExecutable, isBin, err := GetPluginExecutablePath(plugin.Name)
	if err != nil {
		return err
	}

	cmd := []string{}

	if isBin {
		log.Debugf("Run plugin binary (%s)", pluginExecutable)
		cmd = append([]string{pluginExecutable}, args...)
	} else {
		log.Debugf("Run plugin sh (%s)", pluginExecutable)
		cmd = append([]string{"bash", pluginExecutable}, args...)
	}

	exitCode, err := tools.EnvmanRun(pluginEnvstorePath, "", cmd)
	log.Debugf("Plugin run finished with exit code (%d)", exitCode)
	if err != nil {
		return err
	}

	// Read plugin output
	outStr, err := tools.EnvmanJSONPrint(pluginEnvstorePath)
	if err != nil {
		return err
	}

	envList, err := envmanModels.NewEnvJSONList(outStr)
	if err != nil {
		return err
	}

	pluginOutputStr, found := envList[bitrisePluginOutputEnvKey]
	if found {
		log.Debugf("Plugin output: %s", pluginOutputStr)
	}

	return nil
}
Exemplo n.º 26
0
// DownloadPluginFromURL ....
func DownloadPluginFromURL(URL, dst string) error {
	url, err := url.Parse(URL)
	if err != nil {
		return err
	}

	scheme := url.Scheme
	tokens := strings.Split(URL, "/")
	fileName := tokens[len(tokens)-1]

	tmpDstFilePath := ""
	if scheme != "file" {
		OS, arch, err := getOsAndArch()
		if err != nil {
			return err
		}

		urlWithSuffix := URL
		urlSuffix := fmt.Sprintf("-%s-%s", OS, arch)
		if !strings.HasSuffix(URL, urlSuffix) {
			urlWithSuffix = urlWithSuffix + urlSuffix
		}

		urls := []string{urlWithSuffix, URL}

		tmpDir, err := pathutil.NormalizedOSTempDirPath("plugin")
		if err != nil {
			return err
		}
		tmpDst := path.Join(tmpDir, fileName)
		output, err := os.Create(tmpDst)
		if err != nil {
			return err
		}
		defer func() {
			if err := output.Close(); err != nil {
				log.Errorf("Failed to close file, err: %s", err)
			}
		}()

		success := false
		var response *http.Response
		for _, aURL := range urls {

			response, err = http.Get(aURL)
			if response != nil {
				defer func() {
					if err := response.Body.Close(); err != nil {
						log.Errorf("Failed to close response body, err: %s", err)
					}
				}()
			}

			if err != nil {
				log.Errorf("%s", err)
			} else {
				success = true
				break
			}
		}
		if !success {
			return err
		}

		if _, err := io.Copy(output, response.Body); err != nil {
			return err
		}

		tmpDstFilePath = output.Name()
	} else {
		tmpDstFilePath = strings.Replace(URL, scheme+"://", "", -1)
	}

	if err := cmdex.CopyFile(tmpDstFilePath, dst); err != nil {
		return err
	}

	return nil
}
Exemplo n.º 27
0
// InitPaths ...
func InitPaths() error {
	if err := initBitriseWorkPaths(); err != nil {
		return fmt.Errorf("Failed to init bitrise paths, error: %s", err)
	}

	// --- Bitrise TOOLS
	bitriseToolsDirPth := GetBitriseToolsDirPath()
	if err := pathutil.EnsureDirExist(bitriseToolsDirPth); err != nil {
		return err
	}
	pthWithBitriseTools := generatePATHEnvString(os.Getenv("PATH"), bitriseToolsDirPth)
	if err := os.Setenv("PATH", pthWithBitriseTools); err != nil {
		return fmt.Errorf("Failed to set PATH to include BITRISE_HOME/tools! Error: %s", err)
	}

	inputEnvstorePath, err := filepath.Abs(filepath.Join(BitriseWorkDirPath, "input_envstore.yml"))
	if err != nil {
		return fmt.Errorf("Failed to set input envstore path, error: %s", err)
	}
	InputEnvstorePath = inputEnvstorePath

	outputEnvstorePath, err := filepath.Abs(filepath.Join(BitriseWorkDirPath, "output_envstore.yml"))
	if err != nil {
		return fmt.Errorf("Failed to set output envstore path, error: %s", err)
	}
	OutputEnvstorePath = outputEnvstorePath

	formoutPath, err := filepath.Abs(filepath.Join(BitriseWorkDirPath, "formatted_output.md"))
	if err != nil {
		return fmt.Errorf("Failed to set formatted output path, error: %s", err)
	}
	FormattedOutputPath = formoutPath

	currentDir, err := filepath.Abs("./")
	if err != nil {
		return fmt.Errorf("Failed to set current dir, error: %s", err)
	}
	CurrentDir = currentDir

	// BITRISE_SOURCE_DIR
	if os.Getenv(BitriseSourceDirEnvKey) == "" {
		if err := os.Setenv(BitriseSourceDirEnvKey, currentDir); err != nil {
			return fmt.Errorf("Failed to set BITRISE_SOURCE_DIR, error: %s", err)
		}
	}

	// BITRISE_DEPLOY_DIR
	if os.Getenv(BitriseDeployDirEnvKey) == "" {
		deployDir, err := pathutil.NormalizedOSTempDirPath("deploy")
		if err != nil {
			return fmt.Errorf("Failed to set deploy dir, error: %s", err)
		}

		if err := os.Setenv(BitriseDeployDirEnvKey, deployDir); err != nil {
			return fmt.Errorf("Failed to set BITRISE_DEPLOY_DIR, error: %s", err)
		}
	}

	// BITRISE_CACHE_DIR
	if os.Getenv(BitriseCacheDirEnvKey) == "" {
		cacheDir, err := pathutil.NormalizedOSTempDirPath("cache")
		if err != nil {
			return fmt.Errorf("Failed to set cache dir, error: %s", err)
		}

		if err := os.Setenv(BitriseCacheDirEnvKey, cacheDir); err != nil {
			return fmt.Errorf("Failed to set BITRISE_CACHE_DIR, error: %s", err)
		}
	}

	return nil
}
Exemplo n.º 28
0
func TestBitriseSourceDir(t *testing.T) {
	currPth, err := pathutil.NormalizedOSTempDirPath("bitrise_source_dir_test")
	require.NoError(t, err)

	testPths := []string{}
	for i := 0; i < 4; i++ {
		testPth := filepath.Join(currPth, fmt.Sprintf("_test%d", i))
		require.NoError(t, os.RemoveAll(testPth))
		require.NoError(t, os.Mkdir(testPth, 0777))

		// eval symlinks: the Go generated temp folder on OS X is a symlink
		//  from /var/ to /private/var/
		testPth, err = filepath.EvalSymlinks(testPth)
		require.NoError(t, err)

		defer func() { require.NoError(t, os.RemoveAll(testPth)) }()

		testPths = append(testPths, testPth)
	}

	t.Log("BITRISE_SOURCE_DIR defined in Secret")
	{
		inventoryStr := `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
		inventory, err := bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
		require.NoError(t, err)

		configStr := `
format_version: 1.3.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

workflows:
  test:
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[0] + `" ]] ; then
              exit 1
            fi
`
		require.NoError(t, configs.InitPaths())

		config, warnings, err := bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
		require.NoError(t, err)
		require.Equal(t, 0, len(warnings))

		_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
		require.NoError(t, err)
	}

	t.Log("BITRISE_SOURCE_DIR defined in Secret, and in App")
	{
		inventoryStr := `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
		inventory, err := bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
		require.NoError(t, err)

		configStr := `
format_version: 1.3.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

app:
  envs:
  - BITRISE_SOURCE_DIR: "` + testPths[1] + `"

workflows:
  test:
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[1] + `" ]] ; then
              exit 1
            fi
`

		require.NoError(t, configs.InitPaths())

		config, warnings, err := bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
		require.NoError(t, err)
		require.Equal(t, 0, len(warnings))

		_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
		require.NoError(t, err)
	}

	t.Log("BITRISE_SOURCE_DIR defined in Secret, App and Workflow")
	{
		inventoryStr := `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
		inventory, err := bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
		require.NoError(t, err)

		configStr := `
format_version: 1.3.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

app:
  envs:
  - BITRISE_SOURCE_DIR: "` + testPths[1] + `"

workflows:
  test:
    envs:
    - BITRISE_SOURCE_DIR: "` + testPths[2] + `"
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[2] + `" ]] ; then
              exit 1
            fi
`

		require.NoError(t, configs.InitPaths())

		config, warnings, err := bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
		require.NoError(t, err)
		require.Equal(t, 0, len(warnings))

		_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
		require.NoError(t, err)
	}

	t.Log("BITRISE_SOURCE_DIR defined in secret, App, Workflow and Step")
	{
		inventoryStr := `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
		inventory, err := bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
		require.NoError(t, err)

		configStr := `
format_version: 1.3.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

app:
  envs:
  - BITRISE_SOURCE_DIR: "` + testPths[1] + `"

workflows:
  test:
    envs:
    - BITRISE_SOURCE_DIR: "` + testPths[2] + `"
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            envman add --key BITRISE_SOURCE_DIR --value ` + testPths[3] + `
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[3] + `" ]] ; then
              exit 1
            fi
`

		require.NoError(t, configs.InitPaths())

		config, warnings, err := bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
		require.NoError(t, err)
		require.Equal(t, 0, len(warnings))

		_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
		require.NoError(t, err)
	}
}
Exemplo n.º 29
0
func removeStepDefaultsAndFillStepOutputs(stepListItem *models.StepListItemModel, defaultStepLibSource string) error {
	// Create stepIDData
	compositeStepIDStr, workflowStep, err := models.GetStepIDStepDataPair(*stepListItem)
	if err != nil {
		return err
	}
	stepIDData, err := models.CreateStepIDDataFromString(compositeStepIDStr, defaultStepLibSource)
	if err != nil {
		return err
	}

	// Activate step - get step.yml
	tempStepCloneDirPath, err := pathutil.NormalizedOSTempDirPath("step_clone")
	if err != nil {
		return err
	}
	tempStepYMLDirPath, err := pathutil.NormalizedOSTempDirPath("step_yml")
	if err != nil {
		return err
	}
	tempStepYMLFilePath := filepath.Join(tempStepYMLDirPath, "step.yml")

	if stepIDData.SteplibSource == "path" {
		stepAbsLocalPth, err := pathutil.AbsPath(stepIDData.IDorURI)
		if err != nil {
			return err
		}
		if err := cmdex.CopyFile(filepath.Join(stepAbsLocalPth, "step.yml"), tempStepYMLFilePath); err != nil {
			return err
		}
	} else if stepIDData.SteplibSource == "git" {
		if err := cmdex.GitCloneTagOrBranch(stepIDData.IDorURI, tempStepCloneDirPath, stepIDData.Version); err != nil {
			return err
		}
		if err := cmdex.CopyFile(filepath.Join(tempStepCloneDirPath, "step.yml"), tempStepYMLFilePath); err != nil {
			return err
		}
	} else if stepIDData.SteplibSource == "_" {
		// Steplib independent steps are completly defined in workflow
		tempStepYMLFilePath = ""
	} else if stepIDData.SteplibSource != "" {
		if err := tools.StepmanSetup(stepIDData.SteplibSource); err != nil {
			return err
		}
		if err := tools.StepmanActivate(stepIDData.SteplibSource, stepIDData.IDorURI, stepIDData.Version, tempStepCloneDirPath, tempStepYMLFilePath); err != nil {
			return err
		}
	} else {
		return errors.New("Failed to fill step ouputs: unkown SteplibSource")
	}

	// Fill outputs
	if tempStepYMLFilePath != "" {
		specStep, err := ReadSpecStep(tempStepYMLFilePath)
		if err != nil {
			return err
		}

		if workflowStep.Title != nil && specStep.Title != nil && *workflowStep.Title == *specStep.Title {
			workflowStep.Title = nil
		}
		if workflowStep.Description != nil && specStep.Description != nil && *workflowStep.Description == *specStep.Description {
			workflowStep.Description = nil
		}
		if workflowStep.Summary != nil && specStep.Summary != nil && *workflowStep.Summary == *specStep.Summary {
			workflowStep.Summary = nil
		}
		if workflowStep.Website != nil && specStep.Website != nil && *workflowStep.Website == *specStep.Website {
			workflowStep.Website = nil
		}
		if workflowStep.SourceCodeURL != nil && specStep.SourceCodeURL != nil && *workflowStep.SourceCodeURL == *specStep.SourceCodeURL {
			workflowStep.SourceCodeURL = nil
		}
		if workflowStep.SupportURL != nil && specStep.SupportURL != nil && *workflowStep.SupportURL == *specStep.SupportURL {
			workflowStep.SupportURL = nil
		}
		workflowStep.PublishedAt = nil
		if workflowStep.Source != nil && specStep.Source != nil {
			if workflowStep.Source.Git == specStep.Source.Git {
				workflowStep.Source.Git = ""
			}
			if workflowStep.Source.Commit == specStep.Source.Commit {
				workflowStep.Source.Commit = ""
			}
		}
		if isStringSliceWithSameElements(workflowStep.HostOsTags, specStep.HostOsTags) {
			workflowStep.HostOsTags = []string{}
		}
		if isStringSliceWithSameElements(workflowStep.ProjectTypeTags, specStep.ProjectTypeTags) {
			workflowStep.ProjectTypeTags = []string{}
		}
		if isStringSliceWithSameElements(workflowStep.TypeTags, specStep.TypeTags) {
			workflowStep.TypeTags = []string{}
		}
		if isDependencySliceWithSameElements(workflowStep.Dependencies, specStep.Dependencies) {
			workflowStep.Dependencies = []stepmanModels.DependencyModel{}
		}
		if workflowStep.IsRequiresAdminUser != nil && specStep.IsRequiresAdminUser != nil && *workflowStep.IsRequiresAdminUser == *specStep.IsRequiresAdminUser {
			workflowStep.IsRequiresAdminUser = nil
		}
		if workflowStep.IsAlwaysRun != nil && specStep.IsAlwaysRun != nil && *workflowStep.IsAlwaysRun == *specStep.IsAlwaysRun {
			workflowStep.IsAlwaysRun = nil
		}
		if workflowStep.IsSkippable != nil && specStep.IsSkippable != nil && *workflowStep.IsSkippable == *specStep.IsSkippable {
			workflowStep.IsSkippable = nil
		}
		if workflowStep.RunIf != nil && specStep.RunIf != nil && *workflowStep.RunIf == *specStep.RunIf {
			workflowStep.RunIf = nil
		}

		inputs := []envmanModels.EnvironmentItemModel{}
		for _, input := range workflowStep.Inputs {
			sameValue := false

			wfKey, wfValue, err := input.GetKeyValuePair()
			if err != nil {
				return err
			}

			wfOptions, err := input.GetOptions()
			if err != nil {
				return err
			}

			sInput, err := getInputByKey(specStep.Inputs, wfKey)
			if err != nil {
				return err
			}

			_, sValue, err := sInput.GetKeyValuePair()
			if err != nil {
				return err
			}

			if wfValue == sValue {
				sameValue = true
			}

			sOptions, err := sInput.GetOptions()
			if err != nil {
				return err
			}

			hasOptions := false

			if wfOptions.Title != nil && sOptions.Title != nil && *wfOptions.Title == *sOptions.Title {
				wfOptions.Title = nil
			} else {
				hasOptions = true
			}

			if wfOptions.Description != nil && sOptions.Description != nil && *wfOptions.Description == *sOptions.Description {
				wfOptions.Description = nil
			} else {
				hasOptions = true
			}

			if wfOptions.Summary != nil && sOptions.Summary != nil && *wfOptions.Summary == *sOptions.Summary {
				wfOptions.Summary = nil
			} else {
				hasOptions = true
			}

			if isStringSliceWithSameElements(wfOptions.ValueOptions, sOptions.ValueOptions) {
				wfOptions.ValueOptions = []string{}
			} else {
				hasOptions = true
			}

			if wfOptions.IsRequired != nil && sOptions.IsRequired != nil && *wfOptions.IsRequired == *sOptions.IsRequired {
				wfOptions.IsRequired = nil
			} else {
				hasOptions = true
			}

			if wfOptions.IsExpand != nil && sOptions.IsExpand != nil && *wfOptions.IsExpand == *sOptions.IsExpand {
				wfOptions.IsExpand = nil
			} else {
				hasOptions = true
			}

			if wfOptions.IsDontChangeValue != nil && sOptions.IsDontChangeValue != nil && *wfOptions.IsDontChangeValue == *sOptions.IsDontChangeValue {
				wfOptions.IsDontChangeValue = nil
			} else {
				hasOptions = true
			}

			if !hasOptions && sameValue {
				// default env
			} else {
				if hasOptions {
					input[envmanModels.OptionsKey] = wfOptions
				} else {
					delete(input, envmanModels.OptionsKey)
				}

				inputs = append(inputs, input)
			}
		}

		workflowStep.Inputs = inputs

		// We need only key-value and title from spec outputs
		outputs := []envmanModels.EnvironmentItemModel{}
		for _, output := range specStep.Outputs {
			sKey, sValue, err := output.GetKeyValuePair()
			if err != nil {
				return err
			}

			sOptions, err := output.GetOptions()
			if err != nil {
				return err
			}

			newOutput := envmanModels.EnvironmentItemModel{
				sKey: sValue,
				envmanModels.OptionsKey: envmanModels.EnvironmentItemOptionsModel{
					Title: sOptions.Title,
				},
			}

			outputs = append(outputs, newOutput)
		}

		workflowStep.Outputs = outputs

		(*stepListItem)[compositeStepIDStr] = workflowStep
	}

	// Cleanup
	if err := cmdex.RemoveDir(tempStepCloneDirPath); err != nil {
		return errors.New(fmt.Sprint("Failed to remove step clone dir: ", err))
	}
	if err := cmdex.RemoveDir(tempStepYMLDirPath); err != nil {
		return errors.New(fmt.Sprint("Failed to remove step clone dir: ", err))
	}

	return nil
}
Exemplo n.º 30
0
func TestBitriseSourceDir(t *testing.T) {
	currPth, err := pathutil.NormalizedOSTempDirPath("bitrise_source_dir_test")
	if err != nil {
		t.Fatal("Failed to get curr abs path: ", err)
	}

	testPths := []string{}
	for i := 0; i < 4; i++ {
		testPth := path.Join(currPth, fmt.Sprintf("_test%d", i))
		if err := os.RemoveAll(testPth); err != nil {
			t.Fatalf("Failed to remove %s, err: %s: ", testPth, err)
		}

		err := os.Mkdir(testPth, 0777)
		if err != nil {
			t.Fatalf("Failed to create %s, err: %s: ", testPth, err)
		}
		// eval symlinks: the Go generated temp folder on OS X is a symlink
		//  from /var/ to /private/var/
		testPth, err = filepath.EvalSymlinks(testPth)
		if err != nil {
			t.Fatalf("Failed to EvalSymlinks for (path:%s), err: %s", testPth, err)
		}

		defer func() {
			err := os.RemoveAll(testPth)
			if err != nil {
				t.Fatalf("Failed to remove %s, err: %s: ", testPth, err)
			}
		}()

		testPths = append(testPths, testPth)
	}

	//
	// BITRISE_SOURCE_DIR defined in Secret
	inventoryStr := `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
	inventory, err := bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
	require.Equal(t, nil, err)

	configStr := `
format_version: 1.0.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

workflows:
  test:
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[0] + `" ]] ; then
              exit 1
            fi
`
	config, err := bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
	require.Equal(t, nil, err)

	_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
	require.Equal(t, nil, err)

	//
	// BITRISE_SOURCE_DIR defined in Secret, and in App
	inventoryStr = `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
	inventory, err = bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
	require.Equal(t, nil, err)

	configStr = `
format_version: 1.0.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

app:
  envs:
  - BITRISE_SOURCE_DIR: "` + testPths[1] + `"

workflows:
  test:
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[1] + `" ]] ; then
              exit 1
            fi
`
	config, err = bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
	require.Equal(t, nil, err)

	_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
	require.Equal(t, nil, err)

	//
	// BITRISE_SOURCE_DIR defined in Secret, App and Workflow
	inventoryStr = `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
	inventory, err = bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
	require.Equal(t, nil, err)

	configStr = `
format_version: 1.0.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

app:
  envs:
  - BITRISE_SOURCE_DIR: "` + testPths[1] + `"

workflows:
  test:
    envs:
    - BITRISE_SOURCE_DIR: "` + testPths[2] + `"
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[2] + `" ]] ; then
              exit 1
            fi
`
	config, err = bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
	require.Equal(t, nil, err)

	_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
	require.Equal(t, nil, err)

	//
	// BITRISE_SOURCE_DIR defined in Secret, App and Workflow
	//  BUT the value is empty in Workflow and App Envs - Secrets should be used!
	inventoryStr = `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
	inventory, err = bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
	require.Equal(t, nil, err)

	configStr = `
format_version: 1.0.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

app:
  envs:
  - BITRISE_SOURCE_DIR:

workflows:
  test:
    envs:
    - BITRISE_SOURCE_DIR: ""
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[0] + `" ]] ; then
              echo "-> BITRISE_SOURCE_DIR missmatch!"
              exit 1
            fi
            curr_pwd="$(pwd)"
            if [[ "${curr_pwd}" != "` + testPths[0] + `" ]] ; then
              echo "-> pwd missmatch! : curr_pwd : ${curr_pwd}"
              exit 1
            fi
`
	config, err = bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
	require.Equal(t, nil, err)

	_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
	require.Equal(t, nil, err)

	//
	// BITRISE_SOURCE_DIR defined in secret, App, Workflow and Step
	inventoryStr = `
envs:
- BITRISE_SOURCE_DIR: "` + testPths[0] + `"
`
	inventory, err = bitrise.InventoryModelFromYAMLBytes([]byte(inventoryStr))
	require.Equal(t, nil, err)

	configStr = `
format_version: 1.0.0
default_step_lib_source: "https://github.com/bitrise-io/bitrise-steplib.git"

app:
  envs:
  - BITRISE_SOURCE_DIR: "` + testPths[1] + `"

workflows:
  test:
    envs:
    - BITRISE_SOURCE_DIR: "` + testPths[2] + `"
    steps:
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            envman add --key BITRISE_SOURCE_DIR --value ` + testPths[3] + `
    - script:
        inputs:
        - content: |
            #!/bin/bash
            set -v
            echo "BITRISE_SOURCE_DIR: $BITRISE_SOURCE_DIR"
            if [[ "$BITRISE_SOURCE_DIR" != "` + testPths[3] + `" ]] ; then
              exit 1
            fi
`
	config, err = bitrise.ConfigModelFromYAMLBytes([]byte(configStr))
	require.Equal(t, nil, err)

	_, err = runWorkflowWithConfiguration(time.Now(), "test", config, inventory.Envs)
	require.Equal(t, nil, err)
}