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 }
func saveAttachements(projectPath, scheme string) error { projectName := filepath.Base(projectPath) projectExt := filepath.Ext(projectName) projectName = strings.TrimSuffix(projectName, projectExt) userHome := pathutil.UserHomeDir() deviedDataDir := filepath.Join(userHome, "Library/Developer/Xcode/DerivedData") projectDerivedDataDirPattern := filepath.Join(deviedDataDir, fmt.Sprintf("%s-*", projectName)) projectDerivedDataDirs, err := filepath.Glob(projectDerivedDataDirPattern) if err != nil { return err } if len(projectDerivedDataDirs) > 1 { return fmt.Errorf("more than 1 project derived data dir found: %v, with pattern: %s", projectDerivedDataDirs, projectDerivedDataDirPattern) } else if len(projectDerivedDataDirs) == 0 { return fmt.Errorf("no project derived data dir found with pattern: %s", projectDerivedDataDirPattern) } projectDerivedDataDir := projectDerivedDataDirs[0] testLogDir := filepath.Join(projectDerivedDataDir, "Logs", "Test") if exist, err := pathutil.IsDirExists(testLogDir); err != nil { return err } else if !exist { return fmt.Errorf("no test logs found at: %s", projectDerivedDataDir) } testLogAttachmentsDir := filepath.Join(testLogDir, "Attachments") if exist, err := pathutil.IsDirExists(testLogAttachmentsDir); err != nil { return err } else if !exist { return fmt.Errorf("no test attachments found at: %s", testLogAttachmentsDir) } deployDir := os.Getenv("BITRISE_DEPLOY_DIR") if deployDir == "" { return errors.New("No BITRISE_DEPLOY_DIR found") } zipedTestsDerivedDataPath := filepath.Join(deployDir, fmt.Sprintf("%s-xc-test-Attachments.zip", scheme)) if err := cmd.Zip(testLogDir, "Attachments", zipedTestsDerivedDataPath); err != nil { return err } if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_TEST_ATTACHMENTS_PATH", zipedTestsDerivedDataPath); err != nil { log.Warn("Failed to export: BITRISE_XCODE_TEST_ATTACHMENTS_PATH, error: %s", err) } return nil }
func main() { configs := createConfigsModelFromEnvs() configs.print() if err := configs.validate(); err != nil { log.Error("Issue with input: %s", err) os.Exit(1) } fmt.Println() log.Info("Other Configs:") cleanBuild := (configs.IsCleanBuild == "yes") generateCodeCoverage := (configs.GenerateCodeCoverageFiles == "yes") exportUITestArtifacts := (configs.ExportUITestArtifacts == "true") singleBuild := (configs.IsSingleBuild == "true") buildBeforeTest := (configs.ShouldBuildBeforeTest == "yes") retryOnFail := (configs.ShouldRetryTestOnFail == "yes") // Project-or-Workspace flag action := "" if strings.HasSuffix(configs.ProjectPath, ".xcodeproj") { action = "-project" } else if strings.HasSuffix(configs.ProjectPath, ".xcworkspace") { action = "-workspace" } else { log.Error("Iinvalid project file (%s), extension should be (.xcodeproj/.xcworkspace)", configs.ProjectPath) if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_TEST_RESULT", "failed"); err != nil { log.Warn("Failed to export: BITRISE_XCODE_TEST_RESULT, error: %s", err) } os.Exit(1) } log.Detail("* action: %s", action) // Device Destination deviceDestination := fmt.Sprintf("platform=%s,name=%s,OS=%s", configs.SimulatorPlatform, configs.SimulatorDevice, configs.SimulatorOsVersion) log.Detail("* device_destination: %s", deviceDestination) // Output tools versions xcodebuildVersion, err := xcodeutil.GetXcodeVersion() if err != nil { log.Error("Failed to get the version of xcodebuild! Error: %s", err) if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_TEST_RESULT", "failed"); err != nil { log.Warn("Failed to export: BITRISE_XCODE_TEST_RESULT, error: %s", err) } os.Exit(1) } log.Detail("* xcodebuild_version: %s (%s)", xcodebuildVersion.Version, xcodebuildVersion.BuildVersion) xcprettyVersion, err := cmd.GetXcprettyVersion() if err != nil { log.Warn("Failed to get the xcpretty version! Error: %s", err) } else { log.Detail("* xcpretty_version: %s", xcprettyVersion) } // Simulator infos simulator, err := xcodeutil.GetSimulator(configs.SimulatorPlatform, configs.SimulatorDevice, configs.SimulatorOsVersion) if err != nil { log.Error(fmt.Sprintf("failed to get simulator udid, error: %s", err)) if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_TEST_RESULT", "failed"); err != nil { log.Warn("Failed to export: BITRISE_XCODE_TEST_RESULT, error: %s", err) } os.Exit(1) } log.Detail("* simulator_name: %s, UDID: %s, status: %s", simulator.Name, simulator.SimID, simulator.Status) fmt.Println() buildParams := models.XcodeBuildParamsModel{ Action: action, ProjectPath: configs.ProjectPath, Scheme: configs.Scheme, DeviceDestination: deviceDestination, CleanBuild: cleanBuild, } buildTestParams := models.XcodeBuildTestParamsModel{ BuildParams: buildParams, BuildBeforeTest: buildBeforeTest, AdditionalOptions: configs.TestOptions, GenerateCodeCoverage: generateCodeCoverage, } if singleBuild { buildTestParams.CleanBuild = cleanBuild } // // Start simulator if simulator.Status == "Shutdown" { log.Info("Booting simulator (%s)...", simulator.SimID) if err := xcodeutil.BootSimulator(simulator, xcodebuildVersion); err != nil { log.Error(fmt.Sprintf("failed to boot simulator, error: %s", err)) if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_TEST_RESULT", "failed"); err != nil { log.Warn("Failed to export: BITRISE_XCODE_TEST_RESULT, error: %s", err) } os.Exit(1) } if configs.WaitForSimulatorBoot == "yes" { log.Detail("Waiting for simulator boot") progress.SimpleProgress(".", 1*time.Second, func() { time.Sleep(60 * time.Second) }) } fmt.Println() } // // Run build if !singleBuild { if rawXcodebuildOutput, exitCode, buildErr := runBuild(buildParams, configs.OutputTool); buildErr != nil { if err := saveRawOutputToLogFile(rawXcodebuildOutput, false); err != nil { log.Warn("Failed to save the Raw Output, err: %s", err) } log.Warn("xcode build exit code: %d", exitCode) log.Warn("xcode build log:\n%s", rawXcodebuildOutput) log.Error("xcode build failed with error: %s", buildErr) if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_TEST_RESULT", "failed"); err != nil { log.Warn("Failed to export: BITRISE_XCODE_TEST_RESULT, error: %s", err) } os.Exit(1) } } // // Run test rawXcodebuildOutput, exitCode, testErr := runTest(buildTestParams, configs.OutputTool, configs.XcprettyTestOptions, true, retryOnFail) if err := saveRawOutputToLogFile(rawXcodebuildOutput, (testErr == nil)); err != nil { log.Warn("Failed to save the Raw Output, error %s", err) } if exportUITestArtifacts { if err := saveAttachements(configs.ProjectPath, configs.Scheme); err != nil { log.Warn("Failed to export UI test artifacts, error %s", err) } } if testErr != nil { log.Warn("xcode test exit code: %d", exitCode) log.Error("xcode test failed, error: %s", testErr) hint := `If you can't find the reason of the error in the log, please check the raw-xcodebuild-output.log The log file is stored in $BITRISE_DEPLOY_DIR, and its full path is available in the $BITRISE_XCODE_RAW_TEST_RESULT_TEXT_PATH environment variable` log.Warn(hint) if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_TEST_RESULT", "failed"); err != nil { log.Warn("Failed to export: BITRISE_XCODE_TEST_RESULT, error: %s", err) } os.Exit(1) } if err := cmd.ExportEnvironmentWithEnvman("BITRISE_XCODE_TEST_RESULT", "succeeded"); err != nil { log.Warn("Failed to export: BITRISE_XCODE_TEST_RESULT, error: %s", err) } }