Repository: jenkinsci/xcode-plugin Branch: master Commit: 831b1cdc61ba Files: 250 Total size: 784.6 KB Directory structure: gitextract_872818gr/ ├── .github/ │ ├── dependabot.yml │ ├── release-drafter.yml │ └── workflows/ │ └── cd.yaml ├── .gitignore ├── .mvn/ │ ├── extensions.xml │ └── maven.config ├── CHANGELOG.md ├── Jenkinsfile ├── README.md ├── docs/ │ └── images/ │ └── e75543fce396e66c1ad66700d6e74156c2b730db.logo ├── pom.xml └── src/ ├── main/ │ ├── java/ │ │ ├── au/ │ │ │ └── com/ │ │ │ └── rayh/ │ │ │ ├── BuildConfiguration.java │ │ │ ├── DSymFileFilter.java │ │ │ ├── DeveloperProfile.java │ │ │ ├── DeveloperProfileLoader.java │ │ │ ├── ExportIpa.java │ │ │ ├── GlobalConfigurationImpl.java │ │ │ ├── InfoPlist.java │ │ │ ├── JenkinsXCodeBuildOutputParser.java │ │ │ ├── Keychain.java │ │ │ ├── KeychainPasswordAndPath.java │ │ │ ├── KeychainPasswordAndPathBinding.java │ │ │ ├── KeychainPasswordAndPathImpl.java │ │ │ ├── KeychainUnlockStep.java │ │ │ ├── MobileProvisionParser.java │ │ │ ├── ProjectScheme.java │ │ │ ├── ProjectTarget.java │ │ │ ├── ProvisioningProfile.java │ │ │ ├── Team.java │ │ │ ├── XCArchiveFileFilter.java │ │ │ ├── XCodeAction.java │ │ │ ├── XCodeBuildNumberTokenMacro.java │ │ │ ├── XCodeBuildOutputParser.java │ │ │ ├── XCodeBuilder.java │ │ │ ├── XcodeBuildHelpParser.java │ │ │ ├── XcodeBuildListParser.java │ │ │ ├── XcodeCredentialsHelper.java │ │ │ ├── XcodeDeclarativeCredentialsHandler.java │ │ │ ├── XcodeProject.java │ │ │ ├── XcodeProjectFileFilter.java │ │ │ ├── XcodeProjectParser.java │ │ │ ├── XcodeSchemeFileFilter.java │ │ │ ├── XcodeTestSummariesParser.java │ │ │ └── report/ │ │ │ ├── TestCase.java │ │ │ ├── TestError.java │ │ │ ├── TestFailure.java │ │ │ └── TestSuite.java │ │ └── hudson/ │ │ └── plugins/ │ │ └── xcode/ │ │ └── XcodeInstallation.java │ ├── resources/ │ │ ├── au/ │ │ │ └── com/ │ │ │ └── rayh/ │ │ │ ├── DeveloperProfile/ │ │ │ │ ├── config.groovy │ │ │ │ ├── config_ja.properties │ │ │ │ ├── help-description.html │ │ │ │ ├── help-description_ja.html │ │ │ │ ├── help-password.html │ │ │ │ ├── help-password_ja.html │ │ │ │ ├── help.html │ │ │ │ ├── help_ja.html │ │ │ │ └── upload.groovy │ │ │ ├── DeveloperProfileLoader/ │ │ │ │ ├── config.jelly │ │ │ │ └── config_ja.properties │ │ │ ├── ExportIpa/ │ │ │ │ ├── config.jelly │ │ │ │ ├── config_ja.properties │ │ │ │ ├── help-archiveDir.html │ │ │ │ └── help-archiveDir_ja.html │ │ │ ├── GlobalConfigurationImpl/ │ │ │ │ ├── config.jelly │ │ │ │ └── config_ja.properties │ │ │ ├── KeychainPasswordAndPathBinding/ │ │ │ │ ├── config-variables.jelly │ │ │ │ ├── config-variables_ja.properties │ │ │ │ ├── help-inSearchPathVariable.html │ │ │ │ ├── help-inSearchPathVariable_ja.html │ │ │ │ ├── help-keychainPathVariable.html │ │ │ │ ├── help-keychainPathVariable_ja.html │ │ │ │ ├── help-passwordVariable.html │ │ │ │ └── help-passwordVariable_ja.html │ │ │ ├── KeychainPasswordAndPathImpl/ │ │ │ │ ├── credentials.jelly │ │ │ │ ├── credentials_ja.properties │ │ │ │ ├── help-description.html │ │ │ │ ├── help-description_ja.html │ │ │ │ ├── help-id.html │ │ │ │ ├── help-id_ja.html │ │ │ │ ├── help-keychainPath.html │ │ │ │ ├── help-keychainPath_ja.html │ │ │ │ ├── help-password.html │ │ │ │ └── help-password_ja.html │ │ │ ├── KeychainUnlockStep/ │ │ │ │ ├── config.jelly │ │ │ │ └── config_ja.properties │ │ │ ├── Messages.properties │ │ │ ├── Messages_ja.properties │ │ │ └── XCodeBuilder/ │ │ │ ├── config.jelly │ │ │ ├── config_ja.properties │ │ │ ├── help-allowFailingBuildResults.html │ │ │ ├── help-allowFailingBuildResults_ja.html │ │ │ ├── help-buildDir.html │ │ │ ├── help-buildDir_ja.html │ │ │ ├── help-buildIpa.html │ │ │ ├── help-buildIpa_ja.html │ │ │ ├── help-bundleID.html │ │ │ ├── help-bundleIDInfoPlistPath.html │ │ │ ├── help-bundleIDInfoPlistPath_ja.html │ │ │ ├── help-bundleID_ja.html │ │ │ ├── help-cfBundleShortVersionStringValue.html │ │ │ ├── help-cfBundleShortVersionStringValue_ja.html │ │ │ ├── help-cfBundleVersionValue.html │ │ │ ├── help-cfBundleVersionValue_ja.html │ │ │ ├── help-changeBundleID.html │ │ │ ├── help-changeBundleID_ja.html │ │ │ ├── help-cleanBeforeBuild.html │ │ │ ├── help-cleanBeforeBuild_ja.html │ │ │ ├── help-cleanResultBundlePath.html │ │ │ ├── help-cleanResultBundlePath_ja.html │ │ │ ├── help-codeSigningIdentity.html │ │ │ ├── help-codeSigningIdentity_ja.html │ │ │ ├── help-configuration.html │ │ │ ├── help-configuration_ja.html │ │ │ ├── help-embeddedProfileFile.html │ │ │ ├── help-embeddedProfileFile_ja.html │ │ │ ├── help-generateArchive.html │ │ │ ├── help-generateArchive_ja.html │ │ │ ├── help-globalDevelopmentTeam_ja.html │ │ │ ├── help-globalKeychainName_ja.html │ │ │ ├── help-interpretTargetAsRegEx.html │ │ │ ├── help-interpretTargetAsRegEx_ja.html │ │ │ ├── help-ipaName_ja.html │ │ │ ├── help-keychainName.html │ │ │ ├── help-keychainName_ja.html │ │ │ ├── help-keychainPath.html │ │ │ ├── help-keychainPath_ja.html │ │ │ ├── help-keychainPwd.html │ │ │ ├── help-keychainPwd_ja.html │ │ │ ├── help-logfileOutputDirectory.html │ │ │ ├── help-logfileOutputDirectory_ja.html │ │ │ ├── help-resultBundlePath.html │ │ │ ├── help-resultBundlePath_ja.html │ │ │ ├── help-sdk.html │ │ │ ├── help-sdk_ja.html │ │ │ ├── help-signIpaOnXcrun.html │ │ │ ├── help-signIpaOnXcrun_ja.html │ │ │ ├── help-symRoot.html │ │ │ ├── help-symRoot_ja.html │ │ │ ├── help-target.html │ │ │ ├── help-target_ja.html │ │ │ ├── help-unlockKeychain_ja.html │ │ │ ├── help-useLegacyBuildSystem.html │ │ │ ├── help-useLegacyBuildSystem_ja.html │ │ │ ├── help-xcodeProjectFile_ja.html │ │ │ ├── help-xcodeProjectPath_ja.html │ │ │ ├── help-xcodeSchema_ja.html │ │ │ ├── help-xcodeWorkspaceFile_ja.html │ │ │ ├── help-xcodebuildArguments.html │ │ │ └── help-xcodebuildArguments_ja.html │ │ ├── hudson/ │ │ │ └── plugins/ │ │ │ └── xcode/ │ │ │ └── XcodeInstallation/ │ │ │ ├── config.jelly │ │ │ ├── config_it.properties │ │ │ ├── config_ja.properties │ │ │ ├── help-home.html │ │ │ └── help-home_ja.html │ │ └── index.jelly │ └── webapp/ │ ├── help/ │ │ ├── help-appIDandProvisionUUID.html │ │ ├── help-appIDandProvisionUUID_ja.html │ │ ├── help-assetPackManifestURL.html │ │ ├── help-assetPackManifestURL_ja.html │ │ ├── help-automaticSigning.html │ │ ├── help-automaticSigning_ja.html │ │ ├── help-bundleID.html │ │ ├── help-bundleID_ja.html │ │ ├── help-compileBitcode.html │ │ ├── help-compileBitcode_ja.html │ │ ├── help-copyProvisioningProfile.html │ │ ├── help-copyProvisioningProfile_ja.html │ │ ├── help-credentialKeychainId.html │ │ ├── help-credentialKeychainId_ja.html │ │ ├── help-developmentTeamID.html │ │ ├── help-developmentTeamID_ja.html │ │ ├── help-displayImageURL.html │ │ ├── help-displayImageURL_ja.html │ │ ├── help-embedOnDemandResources.html │ │ ├── help-embedOnDemandResources_ja.html │ │ ├── help-fullSizeImageURL.html │ │ ├── help-fullSizeImageURL_ja.html │ │ ├── help-globalDevelopmentTeam.html │ │ ├── help-globalDevelopmentTeam_ja.html │ │ ├── help-globalKeychainName.html │ │ ├── help-globalKeychainName_ja.html │ │ ├── help-importDeveloperProfile.html │ │ ├── help-importDeveloperProfileId.html │ │ ├── help-importDeveloperProfileId_ja.html │ │ ├── help-importDeveloperProfile_ja.html │ │ ├── help-importIntoExistingKeychain.html │ │ ├── help-importIntoExistingKeychain_ja.html │ │ ├── help-importKeychainId.html │ │ ├── help-importKeychainId_ja.html │ │ ├── help-importKeychainName.html │ │ ├── help-importKeychainName_ja.html │ │ ├── help-ipaExportMethod.html │ │ ├── help-ipaExportMethod_ja.html │ │ ├── help-ipaManifestPlistUrl.html │ │ ├── help-ipaManifestPlistUrl_ja.html │ │ ├── help-ipaName.html │ │ ├── help-ipaName_ja.html │ │ ├── help-ipaOutputDirectory.html │ │ ├── help-ipaOutputDirectory_ja.html │ │ ├── help-manifestPlistURL.html │ │ ├── help-manifestPlistURL_ja.html │ │ ├── help-manualSigning.html │ │ ├── help-manualSigning_ja.html │ │ ├── help-onDemandResourcesURL.html │ │ ├── help-onDemandResourcesURL_ja.html │ │ ├── help-provisioningUUID.html │ │ ├── help-provisioningUUID_ja.html │ │ ├── help-readFromProject.html │ │ ├── help-readFromProject_ja.html │ │ ├── help-thinning.html │ │ ├── help-thinning_ja.html │ │ ├── help-unlockKeychain.html │ │ ├── help-unlockKeychain_ja.html │ │ ├── help-uploadBitcode.html │ │ ├── help-uploadBitcode_ja.html │ │ ├── help-uploadSymbols.html │ │ ├── help-uploadSymbols_ja.html │ │ ├── help-xcodeProjectFile.html │ │ ├── help-xcodeProjectFile_ja.html │ │ ├── help-xcodeProjectPath.html │ │ ├── help-xcodeProjectPath_ja.html │ │ ├── help-xcodeSchema.html │ │ ├── help-xcodeSchema_ja.html │ │ ├── help-xcodeToolsVersion.html │ │ ├── help-xcodeToolsVersion_ja.html │ │ ├── help-xcodeWorkspaceFile.html │ │ └── help-xcodeWorkspaceFile_ja.html │ ├── help-cleanTestReports.html │ └── help-xcodebuildArguments.html └── test/ ├── java/ │ ├── Pkcs12.java │ ├── Pkcs7.java │ └── au/ │ └── com/ │ └── rayh/ │ ├── JenkinsXCodeBuildOutputParserTest.java │ ├── OutputParserTests.java │ ├── XCodeBuildHelpParserTest.java │ ├── XCodeBuildListParserTest.java │ ├── XCodeBuildOutputParserTest.java │ ├── XCodeBuilderTest.java │ ├── XcodeProjectParserTest.java │ └── XcodeTestSummariesParserTest.java └── resources/ ├── XCTest_output_complex_1.txt ├── XCTest_output_complex_2.txt ├── XCTest_output_crashing_1.txt ├── XCTest_output_failing_1.txt ├── XCTest_output_failing_2.txt ├── XCTest_output_passing_1.txt ├── xcodebuildhelp-invalid.txt ├── xcodebuildhelp-valid.txt ├── xcodebuildlist-invalid1.txt ├── xcodebuildlist-invalid2.txt └── xcodebuildlist-valid.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/dependabot.yml ================================================ version: 2 updates: - package-ecosystem: maven directory: / schedule: interval: weekly - package-ecosystem: github-actions directory: / schedule: interval: weekly ================================================ FILE: .github/release-drafter.yml ================================================ _extends: .github ================================================ FILE: .github/workflows/cd.yaml ================================================ # Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins name: cd on: workflow_dispatch: check_run: types: - completed jobs: validate: runs-on: ubuntu-latest outputs: should_release: ${{ steps.verify-ci-status.outputs.result == 'success' && steps.interesting-categories.outputs.interesting == 'true' }} steps: - name: Verify CI status uses: jenkins-infra/verify-ci-status-action@v1.2.1 id: verify-ci-status with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} output_result: true - name: Release Drafter uses: release-drafter/release-drafter@v5 if: steps.verify-ci-status.outputs.result == 'success' with: name: next tag: next version: next env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Check interesting categories uses: jenkins-infra/interesting-category-action@v1.2.0 id: interesting-categories if: steps.verify-ci-status.outputs.result == 'success' with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} release: runs-on: ubuntu-latest needs: [validate] if: needs.validate.outputs.should_release == 'true' steps: - name: Check out uses: actions/checkout@v3 with: fetch-depth: 0 - name: Set up JDK 8 uses: actions/setup-java@v3 with: distribution: temurin java-version: 8 - name: Release uses: jenkins-infra/jenkins-maven-cd-action@v1.3.1 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }} MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }} ================================================ FILE: .gitignore ================================================ target work .idea test-* *.iml .DS_Store *.orig /examples TEST-* ================================================ FILE: .mvn/extensions.xml ================================================ io.jenkins.tools.incrementals git-changelist-maven-extension 1.3 ================================================ FILE: .mvn/maven.config ================================================ -Pconsume-incrementals -Pmight-produce-incrementals -Dchangelist.format=%d.v%s ================================================ FILE: CHANGELOG.md ================================================ Changelog === ### Newer versions See [GitHub releases](https://github.com/jenkinsci/xcode-plugin/releases) #### Version 2.0.14 (14th Nov 2019) - ##### Fix backward compatibility problem at Import Developer Profile. #### Version 2.0.13 (14th Nov 2019) - ##### Information to access the macOS keychain has been moved to credentials. - Fixed a bug in the project parser when multiple projects are in the workspace. ([JENKINS-59523](https://issues.jenkins-ci.org/browse/JENKINS-59523), [JENKINS-59609](https://issues.jenkins-ci.org/browse/JENKINS-59609)) #### Version 2.0.12 (27th May 2019) - ##### Allow to unlock/lock keychain on demand. ([JENKINS-56909](https://issues.jenkins-ci.org/browse/JENKINS-56909)) - Modified to encrypt the keychain password. ([PR \#102](https://github.com/jenkinsci/xcode-plugin/pull/102)) - Fix display bug developer profile credentials and more. ([PR \#103](https://github.com/jenkinsci/xcode-plugin/pull/103)) #### Version 2.0.11 (19th Feb 2019) - ##### Added a function to obtain the status of the test from the outline of the test result 'TestSummaries.plist'. #### Version 2.0.10 (19th Nov 2018) - ##### Fix broken Xcode Project Parser. ([JENKINS-54414](http://JENKINS-54414), [JENKINS-54113](https://issues.jenkins-ci.org/browse/JENKINS-54113)) #### Version 2.0.9 (2nd Nov 2018) - ##### Added a option to use the 'Legacy Build System' instead of 'New Builld System' which became available from Xcode 9. #### Version 2.0.8 (10th Oct 2018) - Corresponds when there is no DEVELOPMENT\_TEAM entry in the old Xcode project. - Delete unnecessary error messages. - When copying the provisioning profile from the project location, it needs to be done before Xcode compilation, so it is fixed. - Fixed a bug that error message got mixed when parsing provisioning profile and analysis failed. #### Version 2.0.7 (20th Sep 2018) - Added the ability to copy provisioning profile files to manual code signing. - Change the help for importing developer profile to more detailed one. - Enhance backward compatibility. - Added a function to retrieve information necessary for CodeSign from Xcode project. #### Version 2.0.6 (16th Aug 2018) - Fixed a bug that key chain was not unlocked properly when importing developer profile to keychain. - Added input validation when setting up developer profile loader. - Added input validation when setting up export IPA. - Fix some bugs. #### Version 2.0.5 (9th Aug 2018) - More compatibility for Pipeline. - Added function to import developer profile into existing keychain. - Added a function to set exportOptions.plist an option for deleting Swift symbols when exporting IPA. #### Version 2.0.4 (22th Jun 2018) - I will display an error message if the developer profile is not loaded. #### Version 2.0.3 (18th Jun 2018) - Implemented the ability to export IPA files from already compiled archives. - [JENKINS-50266](https://issues.jenkins-ci.org/browse/JENKINS-50266) : Fix custom xcodebuild arguments not passed through to export archive step. - [JENKINS-51418](https://issues.jenkins-ci.org/browse/JENKINS-51418) : Fix to always be able to use developer team ID as a parameter regardless of automatic code signature. - Fix the Plugin is abnormally terminate if the out of order of lines from Xcodebuild output is changed. - Added a function to retrieve necessary information for code signature from compiled archive. - Support multiple versions of Xcode without using 'EnvInject Plugin'. #### Version 2.0.2 (30th Apr 2018) - We released again due to infrastructure related problems, but the contents are the same as Ver 2.0.1 #### Version 2.0.1 (26th Apr 2018) - Supports Xcode 9 ([PR \#86](https://github.com/jenkinsci/xcode-plugin/pull/86), [PR\#87](https://github.com/jenkinsci/xcode-plugin/pull/87), [JENKINS-47744](https://issues.jenkins-ci.org/browse/JENKINS-45509), [JENKINS-45509](https://issues.jenkins-ci.org/browse/JENKINS-45509)) - Adding Pipeline support for importDeveloperProfile and adding symbols ([PR \#89](https://github.com/jenkinsci/xcode-plugin/pull/89)) #### Version 2.0.0 (24th May 2017) - The plugin now requires Java 7 and Jenkins core \>= 1.625.1 - The plugin now requires Xcode \>= 7 - New : Supports Xcode 7/8 ([PR\#76](https://github.com/jenkinsci/xcode-plugin/pull/76), [PR\#78](https://github.com/jenkinsci/xcode-plugin/pull/78), [JENKINS-44203](https://issues.jenkins-ci.org/browse/JENKINS-44203){.issue-link}, [JENKINS-44151](https://issues.jenkins-ci.org/browse/JENKINS-44151){.issue-link}, [JENKINS-43226](https://issues.jenkins-ci.org/browse/JENKINS-43226){.issue-link}, [JENKINS-43163](https://issues.jenkins-ci.org/browse/JENKINS-43163){.issue-link}, [JENKINS-38799](https://issues.jenkins-ci.org/browse/JENKINS-38799){.issue-link}, [JENKINS-38777](https://issues.jenkins-ci.org/browse/JENKINS-38777){.issue-link}, [JENKINS-34307](https://issues.jenkins-ci.org/browse/JENKINS-34307){.issue-link}) - Replace 'xcrun PackageApplication' by 'xcodebuild -exportArchive' to package ipa - New Development Team parameter which can be configured globally in Jenkins Global settings or locally at the project level - New : Adds regex for parsing UI test failures (for Xcode 8) ([PR\#75](https://github.com/jenkinsci/xcode-plugin/pull/75), [JENKINS-40938](https://issues.jenkins-ci.org/browse/JENKINS-40938){.issue-link}) - New : Adds support ([PR\#74](https://github.com/jenkinsci/xcode-plugin/pull/74), [JENKINS-42457](https://issues.jenkins-ci.org/browse/JENKINS-42457){.issue-link}, [JENKINS-33355](https://issues.jenkins-ci.org/browse/JENKINS-33355){.issue-link}) #### Version 1.4.11 (21th September 2016) Because XXXX happens - Fix: Support configurable ID for developer profile (JENKINS-32987) #### Version 1.4.10 (20th September 2016) - New: Support configurable ID for developer profile (JENKINS-32987) - New: Allow the option not to sign the IPA with xcrun (JENKINS-32370) - Fix: use textarea for Xcode Build Arguments (JENKINS-30228) - Fix: Generating an archive builds the project twice (JENKINS-30362) - Fix: Allowed the use of environment variables in plist url (JENKINS-27236) #### Version 1.4.9 (23rd September 2015) - Fix: only prepend -allTargets for -project builds (JENKINS-28256) - New: Add support for Xcode 7 date format in Unit Testing build task (pull request xcode-plugin/63) #### Version 1.4.8 (28th February, 2015) - Fix: Add timeout to xcodebuild -list to avoid hang on xcode 6 (pull request xcode-plugin/58) - New: Support multiple targets to be passed into xcodebuild (pull request xcode-plugin/43) #### Version 1.4.7 (5th January, 2015) - Fix: XCTest output parsing: support nested/namespaced test suites (JENKINS-26295) - New: XCTest output parsing: handle tests suites exiting with an error (pull request xcode-plugin/54) #### Version 1.4.6 (16th December, 2014) - Fix: broken dSYM packaging (since 1.4.5) - Fix: BUILD\_DATE does not produce the correct last modified date if built on a slave machine (pull request xcode-plugin/50) - Fix: make sure to set provideApplicationVersion properly upon upgrade from per-1.4.1 (JENKINS-26027) - New: developerProfileLoader: use show-keychain-info to display job specific keychain information - New: support XC test output (JENKINS-19955) - New: display warning when simulator SDK selected and IPA about to be packaged (JENKINS-21293) - New: document xcodebuildArguments (JENKINS-13930) #### Version 1.4.5 (10th December, 2014) - Fix: only zip the DSYM if the DSYM file was actually created and fail the build if the operation failed - Fix: Fail the build if we fail to create an ipa. - Fix: "keychain with the same name already exists" (JENKINS-22130) - New: XCode 6 compatibility (pull request xcode-plugin/48) - New: generate\_manifest added ability to generate enterprise distribution manifest plist (pull request xcode-plugin/45) - Fix: getKeychain returns a global keychain preferred over path (pull request xcode-plugin/41) - New: Ability to change the Bundle identifier (CFBundleIdentifier) for an xcode build (pull request xcode-plugin/39) #### Version 1.4.2 (31st December, 2013) - Fix: Avoid NPE on plugin version update (JENKINS-19886, pull request xcode-plugin/37) #### Version 1.4.1 (30th October, 2013) - Fix: performance regression in output parsing (JENKINS-20037, pull request xcode-plugin/36) #### Version 1.4 (2nd Oct, 2013) - New: added an option to produce .xcarchive (JENKINS-14719) - Fix: Fixing show-keychain-info call (JENKINS-xcode-plugin/30) - New: Build wrapper to restore the keychain at the end of the build (pull request xcode-plugin/31) - New: Adding the possibility to provide a pattern for the .ipa file name (pull request xcode-plugin/33) - New: Added an ability to import \*.developerprofile into a build (pull request xcode-plugin/34) - New: UI update: group options into 3 categories (pull request xcode-plugin/28) - New: Introduced the ability to create global keychain configurations - New: Add new option "allow failing build results" (pull request xcode-plugin/25) - Fix: xcodebuild output parser is more lenient (pull request xcode-plugin/19) - Fix: Can't add xcodebuild parameters including whitespace (JENKINS-12800) - New: Add a field for entering code signing identity (pull request xcode-plugin/6) #### Version 1.3.1 (27th March 2012) - Fix: Custom xcodebuild arguments values are not persisted (JENKINS-12510). #### Version 1.3 (20th January 2012) - New : Ability to specify custom arguments to xcodebuild (so that values in project file can be overridden). It is needed to specify custom build options to make in-app unit tests work. - New : Ability to disable clean up of test reports on per-target level, so that it is possible to run several targets in single job and not mess-up test reports. - Fix : The plugin fails by searching for a double .app extension while compressing .dsym (JENKINS-12273) - Fix : The plugin fails to delete previous generated IPA results in a failed build (JENKINS-12237). - Fix : The plugin fails to set default keychain when using an alternate (non login) keychain (By default the login keychain is the default keychain) (JENKINS-12217). - Fix : Restore Java 1.5 runtime compatibility. (JENKINS-12378) #### Version 1.2.2 (19th December 2011) - Fix : Build IPA fails if the plugin is launched on a remote agent using a relative path for its FS Root directory (JENKINS-12144) #### Version 1.2.1 (18th December 2011) - Fix : Build IPA switch doesn't work properly for a default Xcode project always results in FATAL error (JENKINS-12089) #### Version 1.2 (8th December 2011) - New build parameter to specify the build output directory. This overrides the setting in the user's project file, so it will be put into a known directory rather than XcodeDerivedData, etc. This makes it much easier to set up subsequent build steps in Jenkins that do something with the output of the build. It does this by passing the setting CONFIGURATION\_BUILD\_DIR to xcodebuild if a path is set for this new job config value. - Add support for building schemes and workspaces : The plugin now supports two extra configuration parameters `xcodeScheme` and `xcodeWorkspaceFile`. The scheme maps to xcodebuild's parameter "-scheme" and the workspace to "-workspace". The scheme takes precedence over the target setting and the workspace takes precedence over the project setting. #### Version 1.1 (29th November 2011) - Upgrade the token macro plugin to version 1.5.1 to support environment and build variables (JENKINS-11892) - New configuration parameter to set the SYMROOT value passed to the build. This parameter accepts environment and build variables and Macros (JENKINS-11813) - Various code cleanup and improvements. #### Version 1.0.1 (14th November 2011) - Minor fix about the default value and the documentation of the keystore path parameter. #### Version 1.0 (14th November 2011) - Initiated from [Ray Yamamoto Hilton's Xcode plugin for Hudson](http://rayh.com.au/xcode-hudson-plugin) with few changes : - It improves jenkins compatibility, and is available in its update center. - It uses the to configure values of `CFBundleVersion` and `CFBundleShortVersionString` - It allows to configure the keychain to use and to unlock it - It is ready for internationalization If you previously used the version provided by Ray you should be able to test this one in parallel as it has a new identity. Also you'll have to reconfigure a large part of it if you want to upgrade thus don't forget to save your settings. ================================================ FILE: Jenkinsfile ================================================ buildPlugin(platforms: ['linux']) ================================================ FILE: README.md ================================================ Xcode plugin ------------ This plugin adds the ability to call Xcode command line tools to automate build and packaging iOS applications (iPhone, iPad, ...). * Report all issues or features requests in Jira : https://issues.jenkins-ci.org/issues/?jql=component%20%3D%20xcode-plugin Contact the Jenkins Community by [mail](http://jenkins-ci.org/content/mailing-lists) or [irc](http://jenkins-ci.org/content/chat) to have support. *The maintainer is looking for a co-maintainer. I need your help!!* To help us maintain the plugin, you can take contact to jerome.lacoste *at* gmail.com in particular if you are able to test upcoming releases Thank you! A problem, An idea ? *Please use our tasks and issues tracker to report bugs, improvements or new feature.* - [Report a bug](https://issues.jenkins-ci.org/secure/CreateIssueDetails!init.jspa?Create=Create&components=16124&pid=10172&issuetype=1) - [Ask for a new feature](https://issues.jenkins-ci.org/secure/CreateIssueDetails!init.jspa?Create=Create&components=16124&pid=10172&issuetype=2) - [Ask for an improvement of an existing feature](https://issues.jenkins-ci.org/secure/CreateIssueDetails!init.jspa?Create=Create&components=16124&pid=10172&issuetype=4) Also if you want to propose some code change using a Github pull request, please open also a Jira issue. It is easier for developers to track them. *Important!* Newesth version is compatibility with the previous version priour 2.0.12 is maintained. However, major changes have been made to the handling of macOS keychains. Information to access the keychain is moved from configuration to credentials. After that, the information for accessing the keychain must be registered in the credentials. This plugin adds the ability to call Xcode command line tools to automate build and packaging iOS applications (iPhone, iPad, ...). #### Features ##### Versioning This builder can invoke agvtool to dynamically update the `CFBundleVersion` (a.k.a. Technical Version) or `CFBundleShortVersionString` (a.k.a. Marketing Version). It supports all macros from the . For example the value `${BUILD_NUMBER`} will be replaced with the current build number. We advice you to generate a unique value for each build for the `CFBundleVersion` if you want for example deploy it into a private store. In that case you can use for example : `${JOB_NAME}-${BUILD_NUMBER`} ##### Building The target (optional), configuration (e.g. `Debug`, `Release`) and SDK (optional) can be specified in the per-project config along with whether to perform a clean before the build phase. ##### Packaging The builder can be used to package the .app into a .ipa. Since a .app is actually a directory, it can be awkward to work with and, especially, distribute. We can simplify this by packaging the .app into a single .ipa file, which is just a zip file with a well-known internal structure ##### Signing This plugin has two features that help you simplify the code signing process. ###### Allowing Jenkins to stage developer profile This plugin builds on top of to allow you to store your Apple Developer Profile (\*.developerprofile) file. [This file contains a code signing private key, corresponding developer/distribution certificates, and mobile provisioning profiles](http://stackoverflow.com/questions/15154211/what-data-are-stored-in-developer-profile-file-exported-from-xcode). You can [create this file from your XCode](http://stackoverflow.com/questions/10404931/copying-keys-and-certificates-to-another-one-mac-for-iphone-development). To upload the developer profile into Jenkins, go to "Manage Credentials" in the system configuration page, and select "Apple Developer Profile" from the "Add" button. See for further details. To use this profile for signing, add "Import developer profile" as a build step before you run xcode, and select the developer profile to import into the build machine. This build step will install the developer profile into the slave's keychain. ###### Work with existing populated keychains If you create a dedicated keychain that stores the code signing private key and certificate on every build slave, you can configure the plugin to just unlock this keychain (so that xcode can use it for signing) Unlocking If you store your keys in the user keychain (most probably) and if you run jenkins as daemon, make sure you installed a recent version of jenkins for Mac, or configured the daemon to create a session (through the CreationSession=true parameter in your org.jenkins-ci.plist daemon config file). [See also](http://stackoverflow.com/questions/9626447/unable-to-sign-ios-builds-with-jenkins) Timeouts The keychain has a default timeout of 300 seconds. One can override it using the security set-keychain-settings command, which isn't supported in the plugin today. Support in the plugin could be improved by adding options to modify the timeout as part of the build process. See [JENKINS-17184](https://issues.jenkins-ci.org/browse/JENKINS-17184). ##### Unit Testing This plugin will listen to the xcodebuild output when running OCUnit or XC tests and write out JUnit-format test reports that Jenkins can understand. Jenkins will then use these to publish test failure reports and graphs. ##### Sample of the configuration panel ![](docs/images/40d7bd30d112f7b90d88d57fce45ecb2abe29c2e.png) #### Documentation ##### Installation guide Obviously, the build machine has to be an OSX machine with XCode developer tools installed. Certificates, Identities and Provisions must be installed on the build machine separately. Just install the latest version of the plugin from the update center and configure a freestyle job (see \#Usage Guide) that will use your OSX node (If your central instance isn't running under OSX). If xcode related binaries aren't stored in the default location, update the global configuration of the plugin (Manage Jenkins -\> Configure System) ![](docs/images/46781a5731ff4fb8b72f4d780b2b02a402f34a2e.png) If you want to use multiple versions of Xcode to build your application, use ’Global Tool Configuration’ to register the distinguished name and location of the installed Xcode. ![](docs/images/f3e88bf4404d395d55e82786142b77ee217ddbd1.png) ##### Usage guide ###### Import developer profile step By adding the Import developer profile step to Build, you can import developer profiles exported to Xcode into temporary keychains or existing keychains. The developer profile contains a set of certificates, secret keys and provisioning profiles necessary for compiling and signing applications, which is useful for distributing with multiple Jenkins nodes. ###### Import developer profile configuration parameters | Parameter | Pipeline Parameter | Since version | Description | |-------------------------------|----------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Developer Profile | profileId | 2.0.1 | Select the developer profile you exported from Xcode Preference to import into the keychain. Developer profile must be registered with Jenkins in advance by "Credentials". If you do not select this column, you can specify the identifier of the developer profile registered in "Credentials" with the next "Developer Profile ID". | | Import into existing Keychain | importIntoExistingKeychain | 2.0.6 | If it is checked, the developer profile will be imported into the existing keychain. If not checked, create a new key chain with the file name "jenkins-" + "job name" newly, and import the developer profile into this. (In this case, a random character string is automatically generated and used for the password) | | Target keychain | keychainId | 2.0.13 | The ID of the configured keychain to use to import certificates from developer profile to sign the package. | | Target keychain | keychainName
This has been deprecated and has now been replaced by "keychainId".| 2.0.6 | The name of the configured keychain to use to import certificates from developer profile to sign the package. | | Keychain path | keychainPath | 2.0.6 | Keychain path to import developer profile. | | Keychain password | keychainPwd | 2.0.6 | Password to unlock keychain importing developer profile. | Limitations The Xcode Integration Plugin has the function of importing the secret key and certificate of the developer account into the temporary key chain, but as the constraint of macOS can not handle different key chain for each session, the job handling the key chain If you execute them in parallel, this will not work properly. As one of workarounds, it is impossible to limit the maximum number of jobs around Jenkins' node to 1 and to execute multiple nodes with different macOS accounts. ###### Setting up a build step Add the XCode build step to a free-style project and set the target (e.g. `MyApp`), configuration (e.g. `Release`) and check the build IPA and update version number options. This will give you a single, versioned .ipa file. You can also select to clean the project before a build; while this will make sure that the project is starting from a clean state, it will make large projects take a lot longer. ###### Setting up a unit test step Add the XCode build step and this time specify your unit test target (e.g. `MyAppTests`), configuration (e.g. `Debug`) and the SDK (e.g. `Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.1.sdk/`). Leave all the checkboxes unselected. The SDK needs to be supplied here as the unit tests will only be run when building under the simulator's SDK. Check the "Publish JUnit test result report" option in the project config and set the value `"*``/test-reports/``*.xml"` under "Test report XMLs". This will tell Jenkins to pick up the JUnit-format test reports. ###### XCode Builder configuration parameters | Parameter | Pipeline Parameter | Since version | Description | |-------------------------------|---------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |Xcode Workspace File |xcodeWorkspaceFile |1.2 |Only needed if you want to compile a workspace instead of a project. It takes precedence over 'Xcode Project File' setting and this job 'configuration' parameter."| |Xcode Tools Version |xcodeName |2.0.3 |You can select the version of Xcode set by 'Global Tool Configuration' by plugin setting.
If you choose the 'System Default' for Xcode version, plugin will not do anything, so you can switch Xcode using environment variable 'DEVELOPER_DIR' as well. |Xcode Schema File |xcodeSchema |1.2 |Needed if you want to compile for a specific schema instead of a target, or if you want to generate an archive or an IPA.| |Xcode Project File |xcodeProjectFile |1.0 |If there is more than one XCode project file in the project path, you will need to specify the file name of the project you wish to build.
If you need to build all project, you will need to create an XCode build step for each one manually.| |Xcode Project Directory |xcodeProjectPath |1.0 |This is the relative path from the workspace to the directory that contains the XCode project file.
You only need to supply this value if the XCode project you wish to build is not in the root of the workspace.| |Use Legacy Build System? |useLegacyBuildSystem |2.0.9 |Use the old 'Legacy Build System' instead of 'New Build System' of Xcode 9 and later.| |Upload Symbols? |uploadSymbols |2.0.3 |If Checked, include symbols in IPA exporting for App Store.
The default is "Yes" (check is on).| |Upload Bitcode? |uploadBitcode |2.0.3 |If Checked, include bitcode in IPA exporting for App Store.
The default is "Yes" (check is on).| |Unlock Keychain? |unlockKeychain |1.0 |Automatically unlock the keychain before signing the archive?| |Thinning |thinning |2.0.3 |Set this to thin the packages for one or more devices in Xcode when exporting IPA by methods other than App Store.

Available options are:

- \ (Xcode export non-thinned generic application),
- (Xcode export universal applications and all available thinning variants),
-Or for a model identifier a specific device (eg "iPhone 7, 1").
The default is \.| |Technical version |cfBundleVersionValue |1.0 |This will set the CFBundleVersion to the specified string. Supports all macros and also environment and build variables from the Token Macro Plugin. For example the value ${BUILD_NUMBER} will be replaced with the current build number. We advice you to generate a unique value for each build if you want for example deploy it into a private store. In that case you can use for example : ${JOB_NAME}-${BUILD_NUMBER}| |Target |target |1.0 |The target to build. If left empty, this will build all targets in the project. If you wish to build your binary and the unit test module, it is best to do this as two separate steps each with their own target. This was, the iPhone Simulator SDK can be specified for the unit tests.| |SYMROOT |symRoot |1.1 |You only need to supply this value if you want to specify the SYMROOT path to use. If empty, the default SYMROOT path will be used (it could be different depending of your Xcode version). Supports all macros and also environment and build variables from the Token Macro Plugin. For example you can use the value : ${WORKSPACE}/build| |Strip Swift Symbols? |stripSwiftSymbols |2.0.5 |If checked, symbols be stripped from Swift libraries when exporting the application to IPA.| |SDK |sdk |1.0 |You only need to supply this value if you want to specify the SDK to build against. If empty, the SDK will be determined by XCode. If you wish to run OCUnit tests, you will need to use the iPhone Simulator's SDK, for example: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.1.sdk/| |ResultBundlePath |resultBundlePath |2.0.11 |Leave empty, it will not output a test result and will not analyze the test results. relative to the project-directory.| |Provisioning profiles UUID |provisioningProfiles: [provisioningProfileUUID] |2.0.1 |Specify the UUID or Specifire of the provisioning profile to use to sign the application. If the location of the provisioning profile is set instead of the UUID or Specifire, read the UUID from the provisioning profile and use that value. |Provisioning Profiles Bundle ID|provisioningProfiles: [provisioningProfileAppId] |2.0.1 |Specify the Bundle ID of the application for which code sign to be performed.
If the location of the Info.plist file contained in the compiled archive is set instead of the Bundle ID, read the Bundle ID from the Info.plist file and use that value.
Provide version number and run avgtool? provideApplicationVersion 1.4 Provide version number and run avgtool before invoking the build. |Pack on demand resources? |~~embedOnDemandResourcesAssetPacksInBundle~~
assetPacksInBundle| 2.0.3 |Export settings for non App Store.
If the application is using on demand resources and this item is on, the asset pack is included in the application bundle, so you can test the app without the server hosting the asset pack.
If assetPacksBaseURL is not specified, the default is YES (check is on).| |Pack application, build and sign .ipa? |buildIpa |1.0 |The target to build. If left empty, this will build all targets in the project. If you wish to build your binary and the unit test module, it is best to do this as two separate steps each with their own target. This was, the iPhone Simulator SDK can be specified for the unit tests.| |Output directory |ipaOutputDirectory |1.4 |The output directory for the .ipa file, relative to the build directory.| |On demand resources asset URL |~~onDemandResourcesAssetPacksBaseURL~~
assetPacksBaseURL |2.0.3 |Export settings for non-App Store.
If the application is using an on demand resource and assetPacksInBundle is not YES, this must be the base URL that specifies the host of the asset pack. This will set up the app to download the asset pack from the specified URL. | |No Console Log? |noConsoleLog |2.0.1 |Checking this option will not log xcode build output to console output.| |New bundle ID |bundleID |1.4 |The new bundle ID. Usually something like com.companyname.projectname.| |Marketing version |cfBundleShortVersionStringValue|1.0 |This will set the CFBundleShortVersionString to the specified string. Supports all macros and also environment and build variables from the Token Macro Plugin.| |Manual signing? |manualSigning
This has been deprecated and has now been replaced by "signingMethod".|2.0.1 |For this option you need to manually specify the combination of Provisioning profile UUID and BundleID.
This will be useful if you want to change the combination of Provisioning Profile and Certificate used for CodeSign when you build the application.| |Manifest Plist URL |ipaManifestPlistUrl |1.5 |The base URL to use to create a Manifest Plist. If omitted no Manifest Plist will be generated.| |Logfile Output directory |logfileOutputDirectory |2.0.1 |Specify the directory to output the log of xcodebuild.
If you leave it blank, it will be output to "project directory/builds/${BUILD_NUMBER}/log" with other logs.
If an output path is specified, it is output as a xcodebuild.log file in a relative directory under the "build output directory"| |Keychain path |keychainPath |1.0 |The path of the keychain to use to retrieve certificates to sign the package (default : ${HOME}/Library/Keychains/login.keychain).| |Keychain password |keychainPwd |1.0 |The password of the keychain to use to retrieve certificates to sign the package.| |Keychain Id |keychainId
|2.0.13 |The ID of the configured keychain to use to retrieve certificates to sign the package.| |Keychain name |keychainName
This has been deprecated and has now been replaced by "keychainId".|1.4 |The name of the configured keychain to use to retrieve certificates to sign the package.| |Interpret As Regular Expression|interpretTargetAsRegEx |1.4 |Build all entries listed under the "Targets:" section of the xcodebuild -list output that match the regexp.| |Info.plist path |bundleIDInfoPlistPath |1.4 |The path to the info.plist file which contains the CFBundleIdentifier of your project.
Usually something like:
${WORKSPACE}/ProjectName/Project-Info.plist| |Generate Archive? |generateArchive |2.0 |Checking this option will generate an xcarchive of the specified scheme. A workspace and scheme are are also needed for archives.| |Full size image URL |fullSizeImageURL |2.0.3 |Export settings for non App Store.
Specify the URL of the image (512 x 512 pixels) of the icon to be displayed when installing the application using manifest.plist.| |Export method |ipaExportMethod |1.4 |The export method of the .app to generate the .ipa file. Should be one in 'development', 'ad-hoc', 'enterprise' or 'app-store'.| |Display image URL |displayImageURL |2.0.3 |Export settings for non App Store.
Specify the URL of the image (57 x 57 pixels) of the icon to be displayed when installing the application using manifest.plist.| |Development Team ID |developmentTeamID |1.4 |The ID of the Apple development team to use to sign the IPA If 'Development Team' is not selected.| |Development Team |developmentTeamName |1.4 |The name of the configured development team to use to sign the package. As of XCode 8.3, this is required now to sign an ipa (which now uses xcodebuilder).
A development team can be configured here by specifying a Development Team ID, or by creating one in the jenkins global configuration.| |Custom xcodebuild arguments |xcodebuildArguments |1.3 |Passing custom arguments is convenient when you need to change some project options for Jenkins build, but don't want them to persist in project file. For example when running application tests, following settings often are nice fit: GCC_SYMBOLS_PRIVATE_EXTERN=NO COPY_PHASE_STRIP=NO. Otherwise Release build will usually fail because it won't be able to find application symbols to link with test bundle. Arguments are currently separated by space, enclosing them in quotes won't help.| |Copy provisioning profile |copyProvisioningProfile |2.0.7 |If Checked, and the filename of provisioning profile is specified in "Provisioning profile UUID", the specified file is copied to a predetermined place. ("/Users/${HOME}/Library/MobileDevice/Provisioning Profiles/")
This can be used to overwrite the contents of the developer profile or system settings in the provisioning profile in the project deployed from SCM etc.
If the provisioning profile UUID or Specifire is set in "provisioning profile UUID", it does not do anything.
The default is "Yes" (check is on)| |Configuration |configuration |1.0 |This is the name of the configuration as defined in the XCode project. By default there are Debug and Release configurations.| |Compile Bitcode? |compileBitcode |2.0.3 |If checked, Xcode will recompiling Bitcode and exporting IPA for the non App Store.
The default is "Yes" (check is on).| |Code signing settings |signingMethod |2.0.7 |This attribute can take one of the following three values.
"automatic" (Check "Automatic Signing")
Checking this option will automatically generate Provisioning Profile and certificates for signing application.
However, please be aware that using this function will automatically create Provisioning profile and certificates as necessary, so that old Provisioning profile and certificates will be invalid at that time.
"manual" (Check "Manual signing")
For this option you need to manually specify the combination of Provisioning profile UUID and BundleID.
This will be useful if you want to change the combination of Provisioning Profile and Certificate used for CodeSign when you build the application.
"readFromProject" (Check "Read from Xcode Project")
With this option, it automatically retrieve and sets the combination of BundleID and Provisioning profile UUID from the Xcode project file.
This is useful when you want to take over the combination of BundleID and Provisioning profile UUID that you used in the Xcode project (GUI).| |Clean test reports? |cleanTestReports |1.3 |This will delete the processed test reports before invoking the build. Usually it is a good idea only to do it in test targets, otherwise if other Xcode target is built before tests – the build will fail to collect test reports.| |Clean ResultBundlePath? |cleanResultBundlePath |2.0.11 |This will delete the ResultBundlePath before invoking the build.| |Clean before build? |cleanBeforeBuild |1.0 |This will delete the build directories before invoking the build. This will force the rebuilding of ALL dependencies and can make large projects take a lot longer.| |Change bundle ID? |changeBundleID |1.4 |Checking this option will replace the bundle identifier.
You will need to specify which bundle ID (CFBundleIdentifier) to use and where is the Info.plist file located.
This is handy for example when you want to use a different code signing identity in your development projects.| |Build output directory |buildDir |1.2 |The value to use for CONFIGURATION_BUILD_DIR setting (BUILD_DIR in >= 2.0.0). You only need to supply this value if you want the product of the XCode build to be in a location other than the one specified in project settings and this job 'SYMROOT' parameter. Supports all macros and also environment and build variables from the Token Macro Plugin. For example you can use the value : ${WORKSPACE}/build| |Asset pack URL |assetPackManifestURL |2.0.3 |Export settings for non-App Store App.
If the application is using on-demand resources and the application will installing OTA with manifest.plist, this must be the base URL that specifies the host of the asset pack. This will set up the app to download the asset pack from the specified URL.| |Application URL |appURL |2.0.3 |Specify the URL for installing the application when creating the manifest.plist that is necessary when OTA installing the application from Web pages or email.| |Allow failing build results? |allowFailingBuildResults |1.4 |Checking this option will prevent this build step from failing if xcodebuild exits with a non-zero return code.| |.ipa filename pattern |ipaName |1.4 |A pattern for the ipa file name. You may use ${VERSION} and ${BUILD_DATE} (yyyy.MM.dd) in this string| ###### Setting up a Export IPA step If you add the Export IPA step and set up the information necessary for exporting the IPA file, the location of the archive, the export method, code signature information, etc., you can export the IPA from the archive output in the Xcode Build step. ###### Export IPA configuration parameters | Parameter | Pipeline Parameter | Since version | Description | |-------------------------------|---------------------------|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |Development Team |developmentTeamName |2.0.1 |The name of the configured development team to use to sign the package. As of XCode 8.3, this is required now to sign an ipa (which now uses xcodebuilder).
A development team can be configured here by specifying a Development Team ID, or by creating one in the jenkins global configuration.| |Development Team ID |developmentTeamID |2.0.1 |The ID of the Apple development team to use to sign the IPA If 'Development Team' is not selected. |Xcode Tools Version |xcodeName |2.0.3 |You can select the version of Xcode set by 'Global Tool Configuration' by plugin setting.
If you choose the 'System Default' for Xcode version, plugin will not do anything, so you can switch Xcode using environment variable 'DEVELOPER_DIR' as well. |Archive directory |archiveDir |2.0.1 |Specify the location of the path (usually BUILD_DIR specified by xcodebuild) to read the Archive for exporting the IPA file.
Supports all macros and also environment and build variables from the Token Macro Plugin.

For example you can use the value :
${WORKSPACE}/build |Export method |ipaExportMethod |2.0.1 |The export method of the .app to generate the .ipa file. Should be one in 'development', 'ad-hoc', 'enterprise' or 'app-store'. |.ipa filename pattern |ipaName |2.0.1 |A pattern for the ipa file name. You may use ${VERSION} and ${BUILD_DATE} (yyyy.MM.dd) in this string |Output directory |ipaOutputDirectory |2.0.1 |The output directory for the .ipa file, relative to the build directory. |Upload Bitcode? |uploadBitcode |2.0.3 |If Checked, include bitcode in IPA exporting for App Store.
The default is "Yes" (check is on). |Upload Symbols? |uploadSymbols |2.0.3 |If Checked, include symbols in IPA exporting for App Store.
The default is "Yes" (check is on). |Compile Bitcode? |compileBitcode |2.0.3 |If checked, Xcode will recompiling Bitcode and exporting IPA for the non App Store.
The default is "Yes" (check is on). |Thinning |thinning |2.0.3 |Set this to thin the packages for one or more devices in Xcode when exporting IPA by methods other than App Store.

Available options are:
(Xcode export non-thinned generic application),
(Xcode export universal applications and all available thinning variants),
Or for a model identifier a specific device (eg "iPhone 7, 1").

The default is . |Pack on demand resources? |assetPacksInBundle |2.0.3 |Export settings for non App Store.
If the application is using on demand resources and this item is on, the asset pack is included in the application bundle, so you can test the app without the server hosting the asset pack.
If assetPacksBaseURL is not specified, the default is YES (check is on). |On demand resources asset URL |assetPacksBaseURL |2.0.3 |Export settings for non-App Store.
If the application is using an on demand resource and assetPacksInBundle is not YES, this must be the base URL that specifies the host of the asset pack. This will set up the app to download the asset pack from the specified URL. |Application URL |appURL |2.0.3 |Specify the URL for installing the application when creating the manifest.plist that is necessary when OTA installing the application from Web pages or email. |Display image URL |displayImageURL |2.0.3 |Export settings for non App Store.
Specify the URL of the image (57 x 57 pixels) of the icon to be displayed when installing the application using manifest.plist. |Full size image URL |fullSizeImageURL |2.0.3 |Export settings for non App Store.
Specify the URL of the image (512 x 512 pixels) of the icon to be displayed when installing the application using manifest.plist. |Asset pack URL |assetPackManifestURL |2.0.3 |Export settings for non-App Store App.
If the application is using on-demand resources and the application will installing OTA with manifest.plist, this must be the base URL that specifies the host of the asset pack. This will set up the app to download the asset pack from the specified URL. |trip Swift Symbols? |stripSwiftSymbols |2.0.5 |If checked, symbols be stripped from Swift libraries when exporting the application to IPA. |Manual signing? |manualSigning
This has been deprecated and has now been replaced by "signingMethod".|2.0.1|For this option you need to manually specify the combination of Provisioning profile UUID and BundleID.
This will be useful if you want to change the combination of Provisioning Profile and Certificate used for CodeSign when you build the application. |Code signing settings |signingMethod |2.0.7 |This attribute can take one of the following three values.
- "automatic" (Check "Automatic Signing")
Checking this option will automatically generate Provisioning Profile and certificates for signing application.
However, please be aware that using this function will automatically create Provisioning profile and certificates as necessary, so that old Provisioning profile and certificates will be invalid at that time.
- "manual" (Check "Manual signing")
For this option you need to manually specify the combination of Provisioning profile UUID and BundleID.
This will be useful if you want to change the combination of Provisioning Profile and Certificate used for CodeSign when you build the application.
- "readFromProject" (Check "Read from Xcode Project")
With this option, it automatically retrieve and sets the combination of BundleID and Provisioning profile UUID from the Xcode project file.
This is useful when you want to take over the combination of BundleID and Provisioning profile UUID that you used in the Xcode project (GUI). |Provisioning Profiles Bundle ID|provisioningProfiles: [provisioningProfileAppId]|2.0.1|Specify the Bundle ID of the application for which code sign to be performed.
If the location of the Info.plist file contained in the compiled archive is set instead of the Bundle ID, read the Bundle ID from the Info.plist file and use that value. |Provisioning profiles UUID |provisioningProfiles: [provisioningProfileUUID]|2.0.1|Specify the UUID or Specifire of the provisioning profile to use to sign the application. If the location of the provisioning profile is set instead of the UUID or Specifire, read the UUID from the provisioning profile and use that value. |Unlock Keychain? |unlockKeychain |2.0.1 |Automatically unlock the keychain before signing the archive? |Copy provisioning profile |copyProvisioningProfile |2.0.7 |If Checked, and the filename of provisioning profile is specified in "Provisioning profile UUID", the specified file is copied to a predetermined place. ("/Users/${HOME}/Library/MobileDevice/Provisioning Profiles/")
This can be used to overwrite the contents of the developer profile or system settings in the provisioning profile in the project deployed from SCM etc.
If the provisioning profile UUID or Specifire is set in "provisioning profile UUID", it does not do anything.
The default is "Yes" (check is on) |Keychain name |keychainName |2.0.1 |The name of the configured keychain to use to retrieve certificates to sign the package. |Keychain name |keychainName |2.0.1 |The name of the configured keychain to use to retrieve certificates to sign the package. |Keychain path |keychainPath |2.0.1 |The path of the keychain to use to retrieve certificates to sign the package (default : ${HOME}/Library/Keychains/login.keychain). |Keychain password |keychainPwd |2.0.1 |The password of the keychain to use to retrieve certificates to sign the package. #### Compiling Xcode projects and exporting IPApackages using Jenkins's Pipeline function 1. Import developer profile. ``` syntaxhighlighter-pre importDeveloperProfile(importIntoExistingKeychain: false, profileId: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX') ``` 2. Build the project and output the archive. ``` syntaxhighlighter-pre xcodeBuild( xcodeSchema: "${PROJECT_SCHEMA}", ipaOutputDirectory: 'Release', ipaExportMethod: 'app-store', generateArchive: true, buildIpa: true, ipaName: "${BUILD_TARGET}", bundleID: 'com.example.TargetApp', developmentTeamName: "${DEVELOPMENT_TEAM_NAME}", cleanBeforeBuild: true, configuration: 'Release', cfBundleShortVersionStringValue: '1.0.0', cfBundleVersionValue: '1' ) ``` 3. Export the IPA file from the archive. ``` syntaxhighlighter-pre exportIpa( archiveDir: "${WORKSPACE}/${repositoryName}/build/Release-iphoneos", xcodeSchema: "${PROJECT_SCHEMA}", developmentTeamName: "${DEVELOPMENT_TEAM}", configuration: "AdHoc", infoPlistPath: "${INFO_PLIST}", manualSigning: true, provisioningProfiles: [ [provisioningProfileAppId: "${BUNDLE_ID}", provisioningProfileUUID: 'TestApp_AdHoc_Profile.mobileprovision'] [provisioningProfileAppId: "${BUNDLE_ID}.watchkitapp", provisioningProfileUUID: 'TestApp_AdHoc_Profile.mobileprovision'], [provisioningProfileAppId: "${BUNDLE_ID}.watchkitapp.watchkitextension", provisioningProfileUUID: 'TestApp_AdHoc_Profile.mobileprovision'] ], ipaExportMethod: "ad-hoc", ipaName: "${BUILD_TARGET}", ipaOutputDirectory: "AdHoc" ) ``` 4. Upload the exported IPA file. > When using "XCode's" Automatically manage signing ", various ways are required, so please note the points to be noted separately. ##### Using multiple versions of xcode. One can easily support multiple versions by using environment variables. But first one need to install multiple versions on the build server. Here's one strategy: ###### install multiple versions of xcode 0\. Note current config. xcode-select -p 1\. download xcode DMGs from 2\. enable install from everywhere (under System preferences / Security) Without that I had problems installing xcode, without graphical feedback, tested on 10.9.5, freshly booted. Symptoms were: - app not responsive - Getting errors like in /var/log/system.log Someone attempted to start application App:"Xcode" asn:0x0-1b62b61 pid:57656 refs=6 @ 0x7fa5d9f6df40 but it still has \_kLSApplicationLockedInStoppedStateKey=true, so it is is staying stopped. : LASApplication.cp \#2468 SetApplicationInStoppedState() q=LSSession 100027/0x186bb queue 3\. open DMG file, copy app to /Applications. This might take a while. 4\. close /Volumes/Xcode (otherwise installation won't start) 5\. start Xcode, accept agreement, install missing packages if necessary. This might take a while. Close xcode after GUI opens. 6\. move freshly installed Xcode to new path, e.g. sudo mv /Applications/Xcode.app /Applications/Xcode6.1.app (I use this so that the xcode app appears with version number under spotlight) 7\. reset default xcode-select if necessary (installation might have changed it / reset to /Applications/Xcode.app) sudo xcode-select -s /Applications/Xcode6.1.app (Note the part above could be fully automated....) ###### Select the xcode version at runtime 1\. Use EnvInject plugin 2. for jobs that require the non default do something like DEVELOPER\_DIR=/Applications/Xcode6.0.1.app/Contents/Developer under Inject environment variables to the build process ###### Select the xcode version at runtime (Version 2.0.3 or later) 1. Register the distinguished name and location of the installed Xcode using ’Global Tool Configuration’. 2. Select Xcode registered in 'Global Tool Configuration' in Job's 'Xcode Tools Version'. That's it. #### FAQ ##### User interaction is not allowed When code-signing, a prompt may appear on the build machine asking whether to allow keychain access. This will block the build with a message like `"User interaction is not allowed"` until it is dismissed. Just select 'Always Allow' the first time and it shouldn't need to ask again. ![](docs/images/308d472628999c9f1961068c9af34e49a31c76c7.png) If this prompt is not showing on the build machine, you can force it to appear by running the codesign command that failed from a terminal on the build machine: /usr/bin/codesign --force --sign "iPhone Distribution: ..... ##### No Xcode folder is set \[sources\] $ /usr/bin/xcodebuild -version xcode-select: Error: No Xcode folder is set. Run xcode-select -switch \ to set the path to the Xcode folder. Error: /usr/bin/xcode-select returned unexpected error. FATAL: Check your XCode installation. Jenkins cannot retrieve its version. You probably just installed XCode (by default it is in `/Developer`) but its path isn't configured. You can fix it with xcode-select -switch /Developer/ You should now be able to execute `xcodebuild`. Ex : host:\~ user$ /usr/bin/xcodebuild -version Xcode 4.2 Build version 4C199 ##### Xcode 4.3 XCode 4.3 changes [2 things](https://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/WhatsNewXcode/Articles/xcode_4_3.html) that are important for our usage on a slave or a master : - **Command-Line Tools Are Optional** : The command-line tools are not bundled with Xcode 4.3 by default. Instead, they have to be installed using the Components tab of the Downloads preferences panel ![](docs/images/8f2803dc1d2d272296cfa2ba044a3286e29a374c.jpg) - **/Developer No Longer Exists** : You may have to reconfigure its path like this: sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer/ ================================================ FILE: pom.xml ================================================ 4.0.0 org.jenkins-ci.plugins plugin 4.41 xcode-plugin ${revision}-${changelist} hpi Xcode integration This plugin adds the ability to call Xcode command line tools to automate build and packaging iOS applications (iPhone, iPad, ...). https://github.com/jenkinsci/xcode-plugin MIT LICENSE.txt repo rayhilton Ray Yamamoto Hilton ray.hilton@gmail.com aheritier Arnaud Heritier aheritier@apache.org lacostej Jerome Lacoste jerome.lacoste@gmail.com kazuhidet Kazuhide Takahashi kazuhide.t@linux-powered.com scm:git:https://github.com/${gitHubRepo}.git scm:git:git@github.com:${gitHubRepo}.git https://github.com/${gitHubRepo} ${scmTag} repo.jenkins-ci.org https://repo.jenkins-ci.org/public/ repo.jenkins-ci.org https://repo.jenkins-ci.org/public/ io.jenkins.tools.bom bom-2.319.x 1466.v85a_616ea_b_87c pom import org.jenkins-ci.plugins credentials org.jenkins-ci.plugins token-macro org.jenkins-ci.plugins.workflow workflow-cps true com.googlecode.plist dd-plist 1.23 org.jenkins-ci.plugins structs org.jenkins-ci.plugins credentials-binding org.jenkinsci.plugins pipeline-model-extensions org.jenkinsci.plugins pipeline-model-definition org.bouncycastle bcpkix-jdk15on 1.70 test io.jenkins.plugins jaxb 2.3.6-1 2.0.17 999999-SNAPSHOT jenkinsci/xcode-plugin 2.319.1 org.jenkins-ci.tools maven-hpi-plugin true 2.0.0 ================================================ FILE: src/main/java/au/com/rayh/BuildConfiguration.java ================================================ package au.com.rayh; import com.dd.plist.NSDictionary; import com.dd.plist.NSArray; import com.dd.plist.NSNumber; import com.dd.plist.NSObject; import com.dd.plist.NSString; import com.dd.plist.PropertyListFormatException; import com.dd.plist.PropertyListParser; public class BuildConfiguration { public String uuid; public String name; public String bundleIdentifier; public String infoPlistFile; //public String codeSignStyle; public String developmentTeamId; public String provisioningProfileUUID; public String provisioningProfileSpecifier; public String productName; BuildConfiguration(NSDictionary objectsDict, String buildConfigurationUUID, Boolean automatic) { NSDictionary buildConfigurationDict = ((NSDictionary)objectsDict.objectForKey(buildConfigurationUUID.toString())); //String baseConfigurationReference = buildConfigurationDict.objectForKey("baseConfigurationReference").toString(); this.uuid = buildConfigurationUUID.toString(); this.name = buildConfigurationDict.objectForKey("name").toString(); System.out.println("buildConfigurationUUID: " + this.uuid); NSDictionary buildSettingsDict = ((NSDictionary)buildConfigurationDict.objectForKey("buildSettings")); if ( buildSettingsDict == null ) { System.out.println("buildSettings not exists!"); return; } // LastUpgradeCheck = 0630, CreatedOnToolsVersion = 6.3.1 if ( buildSettingsDict.objectForKey("PRODUCT_BUNDLE_IDENTIFIER") != null ) { this.bundleIdentifier = buildSettingsDict.objectForKey("PRODUCT_BUNDLE_IDENTIFIER").toString(); } else if ( buildSettingsDict.objectForKey("PRODUCT_NAME") != null ) { this.productName = buildSettingsDict.objectForKey("PRODUCT_NAME").toString(); } this.infoPlistFile = buildSettingsDict.objectForKey("INFOPLIST_FILE").toString(); //this.codeSignStyle = buildSettingsDict.objectForKey("CODE_SIGN_STYLE").toString(); if ( buildSettingsDict.objectForKey("BUNDLE_LOADER") == null && buildSettingsDict.objectForKey("TEST_TARGET_NAME") == null && buildSettingsDict.objectForKey("DEVELOPMENT_TEAM") != null ) { this.developmentTeamId = buildSettingsDict.objectForKey("DEVELOPMENT_TEAM").toString(); } if ( !automatic ) { this.provisioningProfileUUID = buildSettingsDict.objectForKey("PROVISIONING_PROFILE").toString(); this.provisioningProfileSpecifier = buildSettingsDict.objectForKey("PROVISIONING_PROFILE_SPECIFIER").toString(); } //else { // this.codeSignStyle = "Automatic"; //} } } ================================================ FILE: src/main/java/au/com/rayh/DSymFileFilter.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package au.com.rayh; import java.io.File; import java.io.FileFilter; import java.io.Serializable; /** * * @author lampietti */ public class DSymFileFilter implements FileFilter, Serializable { public boolean accept(File pathname) { return pathname.isDirectory() && pathname.getName().endsWith(".dSYM"); } } ================================================ FILE: src/main/java/au/com/rayh/DeveloperProfile.java ================================================ package au.com.rayh; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.domains.DomainRequirement; import hudson.Extension; import hudson.security.ACL; import hudson.util.IOUtils; import hudson.util.Secret; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import jenkins.security.ConfidentialKey; import org.apache.commons.fileupload.FileItem; import org.kohsuke.stapler.DataBoundConstructor; import com.cloudbees.plugins.credentials.CredentialsScope; import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials; /** * Apple developer profile, which consists of any number of PKCS12 of the private key * and the certificate for code signing, and mobile provisioning profiles. * * @author Kohsuke Kawaguchi */ public class DeveloperProfile extends BaseStandardCredentials { /** * Password of the PKCS12 files inside the profile. */ private Secret password; @DataBoundConstructor public DeveloperProfile(@CheckForNull CredentialsScope scope, @CheckForNull String id, @CheckForNull String description, Secret password, FileItem image) throws IOException { super(scope, id, description); this.password = password; if (image!=null) { // for added secrecy, store this in the confidential store new ConfidentialKeyImpl(id).store(image); } } @Deprecated public DeveloperProfile(String id, String description, Secret password, FileItem image) throws IOException { this(CredentialsScope.GLOBAL,id,description,password,image); } public Secret getPassword() { return password; } /** * Retrieves the PKCS12 byte image. * @return PKCS12 byte image * @throws IOException file I/O */ public byte[] getImage() throws IOException { return new ConfidentialKeyImpl(getId()).load(); } /** * Obtains the certificates in this developer profile. * @return X509Certificates * @throws IOException file I/O * @throws GeneralSecurityException Certificate error */ public @NonNull List getCertificates() throws IOException, GeneralSecurityException { try (ZipInputStream zip = new ZipInputStream(new ByteArrayInputStream(getImage()))) { List r = new ArrayList<>(); ZipEntry ze; while ((ze = zip.getNextEntry()) != null) { if (ze.getName().endsWith(".p12")) { KeyStore ks = KeyStore.getInstance("pkcs12"); ks.load(zip, password.getPlainText().toCharArray()); Enumeration en = ks.aliases(); while (en.hasMoreElements()) { String s = en.nextElement(); Certificate c = ks.getCertificate(s); if (c instanceof X509Certificate) { r.add((X509Certificate) c); } } } } return r; } } public String getDisplayNameOf(X509Certificate p) { String name = p.getSubjectDN().getName(); try { LdapName n = new LdapName(name); for (Rdn rdn : n.getRdns()) { if (rdn.getType().equalsIgnoreCase("CN")) return rdn.getValue().toString(); } } catch (InvalidNameException e) { // fall through } return name; // fallback } @Extension public static class DescriptorImpl extends BaseStandardCredentialsDescriptor { @Override public String getDisplayName() { return "Apple Developer Profile"; } } static class ConfidentialKeyImpl extends ConfidentialKey { ConfidentialKeyImpl(String id) { super(DeveloperProfile.class.getName()+"."+id); } public void store(FileItem submitted) throws IOException { super.store(IOUtils.toByteArray(submitted.getInputStream())); } public @CheckForNull byte[] load() throws IOException { return super.load(); } } public static List getAllProfiles() { return CredentialsProvider.lookupCredentials(DeveloperProfile.class, (hudson.model.Item)null, ACL.SYSTEM, Collections.emptyList()); } } ================================================ FILE: src/main/java/au/com/rayh/DeveloperProfileLoader.java ================================================ package au.com.rayh; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.AbortException; import hudson.EnvVars; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.model.Item; import hudson.model.Run; import hudson.model.TaskListener; import hudson.remoting.VirtualChannel; import hudson.security.ACL; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; import hudson.util.ListBoxModel; import hudson.util.Secret; import jenkins.model.Jenkins; import jenkins.security.MasterToSlaveCallable; import org.jenkinsci.plugins.tokenmacro.MacroEvaluationException; import org.jenkinsci.plugins.tokenmacro.TokenMacro; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.Symbol; import org.jenkinsci.remoting.RoleChecker; import org.kohsuke.stapler.AncestorInPath; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.CheckForNull; import javax.inject.Inject; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.UUID; /** * Installs {@link DeveloperProfile} into the current slave and unlocks its keychain * in preparation for the signing that uses it. * * TODO: destroy identity in the end. * * @author Kohsuke Kawaguchi */ @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") public class DeveloperProfileLoader extends Builder implements SimpleBuildStep { @CheckForNull private String profileId; @CheckForNull private Boolean importIntoExistingKeychain; @CheckForNull private String keychainId; @Deprecated @CheckForNull private String keychainName; @CheckForNull private String keychainPath; @CheckForNull private Secret keychainPwd; @CheckForNull public String getProfileId() { return profileId; } @DataBoundSetter public void setProfileId(String developerProfileId) { this.profileId = developerProfileId; } public Boolean getImportIntoExistingKeychain() { return importIntoExistingKeychain == null ? Boolean.valueOf(false) : importIntoExistingKeychain; } @DataBoundSetter public void setImportIntoExistingKeychain(Boolean importIntoExistingKeychain ) { this.importIntoExistingKeychain = importIntoExistingKeychain; } @CheckForNull public String getKeychainId() { return keychainId; } @Deprecated @CheckForNull public String getKeychainName() { return keychainName; } @DataBoundSetter public void setKeychainId(String keychainId) { this.keychainId = keychainId; } @Deprecated @DataBoundSetter public void setKeychainName(String keychainName) { this.keychainName = keychainName; } @CheckForNull public String getKeychainPath() { return keychainPath; } @DataBoundSetter public void setKeychainPath(String keychainPath) { this.keychainPath = keychainPath; } @CheckForNull public Secret getKeychainPwd() { return keychainPwd; } @DataBoundSetter public void setKeychainPwd(Secret keychainPwd) { this.keychainPwd = keychainPwd; } @DataBoundConstructor public DeveloperProfileLoader() { } @Deprecated public DeveloperProfileLoader(String profileId) { this(); this.profileId = profileId; } @Override public void perform(@NonNull Run run, @NonNull FilePath workspace, @NonNull Launcher launcher, @NonNull TaskListener listener) throws InterruptedException, IOException { EnvVars envs = run.getEnvironment(listener); String _profileId = envs.expand(this.profileId); String _keychainId = envs.expand(this.keychainId); String _keychainName = envs.expand(this.keychainName); Boolean _importIntoExistingKeychain = this.importIntoExistingKeychain; DeveloperProfile dp = getProfile(run.getParent(), _profileId); if ( dp == null ) throw new AbortException(Messages.DeveloperProfile_NoDeveloperProfileConfigured()); String _keychainPath; String _keychainPwd; if ( BooleanUtils.isTrue(_importIntoExistingKeychain)) { if ( StringUtils.isNotEmpty(_keychainName) ) { // for backward compatibility listener.getLogger().println(Messages.XCodeBuilder_UseDeprecatedKeychainInfo()); Keychain keychain = getKeychain(_keychainName); if (keychain == null) { throw new AbortException(Messages.DeveloperProfileLoader_NoKeychainInfoConfigured()); } else { _keychainPath = envs.expand(keychain.getKeychainPath()); _keychainPwd = envs.expand(Secret.toString(keychain.getKeychainPassword())); _importIntoExistingKeychain = Boolean.valueOf(true); } } else if ( StringUtils.isNotEmpty(_keychainId) ) { KeychainPasswordAndPath keychain = getKeychainPasswordAndPath(run.getParent(), _keychainId); if ( keychain == null ) { throw new AbortException(Messages.DeveloperProfileLoader_NoKeychainInfoConfigured()); } else { _keychainPath = envs.expand(keychain.getKeychainPath()); _keychainPwd = envs.expand(keychain.getPassword().getPlainText()); _importIntoExistingKeychain = Boolean.valueOf(true); } } else { if ( StringUtils.isNotEmpty(this.keychainPath) && StringUtils.isNotEmpty(Secret.toString(this.keychainPwd)) ) { _keychainPath = envs.expand(this.keychainPath); _keychainPwd = envs.expand(Secret.toString(this.keychainPwd)); } else { throw new AbortException(Messages.DeveloperProfileLoader_KeychainPathOrPasswordIsBlank()); } } } else { // Use temporary keychain with random UUID nasme. _keychainPath = "jenkins-" + run.getParent().getFullName().replace('/', '-'); _keychainPwd = UUID.randomUUID().toString(); _importIntoExistingKeychain = Boolean.valueOf(false); } // Note: keychain are usualy suffixed with .keychain. If we change we should probably clean up the ones we created ArgumentListBuilder args; if ( BooleanUtils.isNotTrue(_importIntoExistingKeychain) ) { // if the key chain is already present, delete it and start fresh ByteArrayOutputStream out = new ByteArrayOutputStream(); args = new ArgumentListBuilder("security", "delete-keychain", _keychainPath); launcher.launch().cmds(args).stdout(out).join(); args = new ArgumentListBuilder("security", "create-keychain"); args.add("-p").addMasked(_keychainPwd); args.add(_keychainPath); invoke(launcher, listener, args, "Failed to create a keychain"); } args = new ArgumentListBuilder("security", "unlock-keychain"); args.add("-p").addMasked(_keychainPwd); args.add(_keychainPath); invoke(launcher, listener, args, "Failed to unlock keychain"); if ( BooleanUtils.isNotTrue(_importIntoExistingKeychain) ) { args = new ArgumentListBuilder("security", "list-keychains"); args.add("-d").add("user"); args.add("-s").add("login.keychain"); args.add(_keychainPath); invoke(launcher, listener, args, "Failed to set keychain search path"); } final FilePath secret = getSecretDir(workspace, _keychainPwd); final byte[] dpImage = dp.getImage(); if ( dpImage == null ) throw new AbortException(Messages.DeveloperProfile_NoDeveloperProfileConfigured()); secret.unzipFrom(new ByteArrayInputStream(dpImage)); // import identities for ( FilePath id : secret.list("**/*.p12") ) { args = new ArgumentListBuilder("security", "import"); args.add(id).add("-k", _keychainPath); args.add("-P").addMasked(dp.getPassword().getPlainText()); args.add("-T", "/usr/bin/codesign"); args.add("-T", "/usr/bin/productsign"); args.add(_keychainPath); invoke(launcher, listener, args, "Failed to import identity " + id); } { // display keychain info for potential troubleshooting args = new ArgumentListBuilder("security", "show-keychain-info"); args.add(_keychainPath); ByteArrayOutputStream output = invoke(launcher, listener, args, "Failed to show keychain info"); listener.getLogger().write(output.toByteArray()); } if ( BooleanUtils.isNotTrue(_importIntoExistingKeychain) ) { args = new ArgumentListBuilder("security", "set-key-partition-list"); args.add("-S").add("apple-tool:,apple:"); args.add("-s").add("-k").addMasked(_keychainPwd); args.add(_keychainPath); invoke(launcher, listener, args, "Failed to set key partition list to keychain"); } { // If default keychain is not set, set the specified keychain to default keychain. args = new ArgumentListBuilder("security", "default-keychain"); ByteArrayOutputStream output = new ByteArrayOutputStream(); if ( launcher.launch().cmds(args).stdout(output).join() != 0 ) { listener.getLogger().write(output.toByteArray()); String strResult = new String(output.toByteArray(), "UTF-8"); if ( strResult.contains("A default keychain could not be found.") ) { args = new ArgumentListBuilder("security", "default-keychain"); args.add("-d").add("user"); args.add("-s").add(_keychainPath); invoke(launcher, listener, args, "Failed to set default keychain"); } } } if ( BooleanUtils.isNotTrue(_importIntoExistingKeychain) ) { importAppleCert(launcher, listener, workspace, _keychainPath); } // copy provisioning profiles VirtualChannel ch = launcher.getChannel(); FilePath home = ch.call(new GetHomeDirectory()); // TODO: switch to FilePath.getHomeDirectory(ch) when we can FilePath profiles = home.child("Library/MobileDevice/Provisioning Profiles"); profiles.mkdirs(); for ( FilePath mp : secret.list("**/*.mobileprovision") ) { listener.getLogger().println(Messages.DeveloperProfile_Installing(mp.getName())); mp.copyTo(profiles.child(mp.getName())); } } @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { perform(build, build.getWorkspace(), launcher, listener); return true; } @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } public GlobalConfigurationImpl getGlobalConfiguration() { return getDescriptor().getGlobalConfiguration(); } public Keychain getKeychain(String keychainName) { if ( !StringUtils.isEmpty(keychainName) ) { for ( Keychain keychain : getGlobalConfiguration().getKeychains() ) { if ( keychain.getKeychainName().equals(keychainName) ) return keychain; } } if ( !StringUtils.isEmpty(this.keychainPath) ) { Keychain newKeychain = new Keychain(); newKeychain.setKeychainPath(this.keychainPath); newKeychain.setKeychainPassword(this.keychainPwd); return newKeychain; } return null; } public KeychainPasswordAndPath getKeychainPasswordAndPath(Item context, String keychainId) { return (KeychainPasswordAndPath)CredentialsMatchers.firstOrNull( CredentialsProvider.lookupCredentials(KeychainPasswordAndPath.class, context, ACL.SYSTEM, Collections.EMPTY_LIST), CredentialsMatchers.withId(keychainId)); } public void importAppleCert(Launcher launcher, TaskListener listener, FilePath workspace, String keychainPath) throws IOException, InterruptedException { ByteArrayOutputStream out = new ByteArrayOutputStream(); FilePath homeFolder = workspace.getHomeDirectory(workspace.getChannel()); String homePath = homeFolder.getRemote(); String cert = homePath + "/AppleWWDRCA.cer"; launcher .launch() .cmds("security", "import", cert, "-k", keychainPath) .stdout(out) .join(); listener.getLogger().write(out.toByteArray()); } private ByteArrayOutputStream invoke(Launcher launcher, TaskListener listener, ArgumentListBuilder args, String errorMessage) throws IOException, InterruptedException { ByteArrayOutputStream output = new ByteArrayOutputStream(); if (launcher.launch().cmds(args).stdout(output).join()!=0) { listener.getLogger().write(output.toByteArray()); throw new AbortException(errorMessage); } return output; } private FilePath getSecretDir(FilePath workspace, String keychainPwd) throws IOException, InterruptedException { FilePath secrets = workspace.child("jenkins").child("developer-profiles"); secrets.mkdirs(); secrets.chmod(0700); return secrets.child(keychainPwd); } public DeveloperProfile getProfile(Item context, String profileId) { return (DeveloperProfile)CredentialsMatchers.firstOrNull( CredentialsProvider.lookupCredentials(DeveloperProfile.class, context, ACL.SYSTEM, Collections.EMPTY_LIST), CredentialsMatchers.withId(profileId)); } @Extension @Symbol("importDeveloperProfile") public static class DescriptorImpl extends BuildStepDescriptor { GlobalConfigurationImpl globalConfiguration; @SuppressFBWarnings("UWF_UNWRITTEN_FIELD") @Inject void setGlobalConfiguration(GlobalConfigurationImpl c) { this.globalConfiguration = c; } @Override public boolean isApplicable(Class jobType) { return true; } @Override public String getDisplayName() { return Messages.DeveloperProfile_ImportDeveloperProfile(); } public ListBoxModel doFillProfileIdItems(@AncestorInPath Item context) { List profiles = CredentialsProvider .lookupCredentials(DeveloperProfile.class, context, null); ListBoxModel r = new ListBoxModel(); for (DeveloperProfile p : profiles) { r.add(p.getDescription(), p.getId()); } return r; } public GlobalConfigurationImpl getGlobalConfiguration() { return globalConfiguration; } public String getUUID() { return "" + UUID.randomUUID().getMostSignificantBits(); } public FormValidation doCheckDeveloperProfileId(@QueryParameter String value) { if ( StringUtils.isEmpty(value) ) { return FormValidation.error(Messages.DeveloperProfileLoader_MustSelectDeveloperProfile()); } return FormValidation.ok(); } public FormValidation doCheckKeychainPath(@QueryParameter String value, @QueryParameter String keychainName, @QueryParameter Boolean importIntoExistingKeychain) { if ( BooleanUtils.isTrue(importIntoExistingKeychain) ) { if ( StringUtils.isEmpty(keychainName) && StringUtils.isEmpty(value) ) { return FormValidation.error(Messages.DeveloperProfileLoader_MustSpecifyKeychainPath()); } } return FormValidation.ok(); } public FormValidation doCheckKeychainPwd(@QueryParameter Secret value, @QueryParameter String keychainName, @QueryParameter Boolean importIntoExistingKeychain) { if ( BooleanUtils.isTrue(importIntoExistingKeychain) ) { if ( StringUtils.isEmpty(keychainName) && StringUtils.isEmpty(Secret.toString(value)) ) { return FormValidation.error(Messages.DeveloperProfileLoader_MustSpecifyKeychainPwd()); } } return FormValidation.ok(); } } private static final class GetHomeDirectory extends MasterToSlaveCallable { public FilePath call() throws IOException { return new FilePath(new File(System.getProperty("user.home"))); } @Override public void checkRoles(RoleChecker roleChecker) throws SecurityException { } } } ================================================ FILE: src/main/java/au/com/rayh/ExportIpa.java ================================================ package au.com.rayh; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.*; import hudson.model.*; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; import hudson.util.Secret; import jenkins.tasks.SimpleBuildStep; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import javax.inject.Inject; import edu.umd.cs.findbugs.annotations.CheckForNull; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ExportIpa extends Builder implements SimpleBuildStep { private static final String[] VALID_IPA_EXPORT_METHODS = { "development", "ad-hoc", "enterprise", "app-store" }; @CheckForNull private String xcodeProjectPath; @CheckForNull private String xcodeProjectFile; @CheckForNull private Boolean unlockKeychain; @Deprecated @CheckForNull private String keychainName; @CheckForNull private String keychainPath; @CheckForNull private Secret keychainPwd; @CheckForNull private String symRoot; @CheckForNull private String xcodeWorkspaceFile; @CheckForNull private String xcodeSchema; @CheckForNull private String archiveDir; @CheckForNull private String developmentTeamName; @CheckForNull private String developmentTeamID; @CheckForNull private String ipaName; @CheckForNull private String ipaOutputDirectory; @CheckForNull private String ipaExportMethod; /** * @deprecated 2.0.7 * @CheckForNull private Boolean manualSigning; */ @CheckForNull private String signingMethod; @CheckForNull private ArrayList provisioningProfiles; @CheckForNull private String xcodeName; @CheckForNull private Boolean uploadBitcode; @CheckForNull private Boolean uploadSymbols; @CheckForNull private Boolean compileBitcode; @CheckForNull private String thinning; @CheckForNull private Boolean embedOnDemandResourcesAssetPacksInBundle; @CheckForNull private String onDemandResourcesAssetPacksBaseURL; @CheckForNull private String appURL; @CheckForNull private String displayImageURL; @CheckForNull private String fullSizeImageURL; @CheckForNull private String assetPackManifestURL; /** * @since 2.0.5 */ @CheckForNull private Boolean stripSwiftSymbols; /** * @since 2.0.7 */ @CheckForNull private Boolean copyProvisioningProfile; /* * @since 2.0.13 */ @CheckForNull private String keychainId; @CheckForNull public String getXcodeProjectPath() { return xcodeProjectPath; } @DataBoundSetter public void setXcodeProjectPath(String xcodeProjectPath) { this.xcodeProjectPath = xcodeProjectPath; } @CheckForNull public String getXcodeProjectFile() { return xcodeProjectFile; } public Boolean getUnlockKeychain() { return unlockKeychain; } @DataBoundSetter public void setUnlockKeychain(Boolean unlockKeychain) { this.unlockKeychain = unlockKeychain; } @CheckForNull public String getKeychainName() { return keychainName; } @DataBoundSetter public void setKeychainName(String keychainName) { this.keychainName = keychainName; } @CheckForNull public String getKeychainPath() { return keychainPath; } @DataBoundSetter public void setKeychainPath(String keychainPath) { this.keychainPath = keychainPath; } @CheckForNull public Secret getKeychainPwd() { return keychainPwd; } @DataBoundSetter public void setKeychainPwd(Secret keychainPwd) { this.keychainPwd = keychainPwd; } @CheckForNull public String getSymRoot() { return symRoot; } @DataBoundSetter public void setSymRoot(String symRoot) { this.symRoot = symRoot; } @CheckForNull public String getXcodeWorkspaceFile() { return xcodeWorkspaceFile; } @DataBoundSetter public void setXcodeWorkspaceFile(String xcodeWorkspaceFile) { this.xcodeWorkspaceFile = xcodeWorkspaceFile; } @CheckForNull public String getXcodeSchema() { return xcodeSchema; } @DataBoundSetter public void setXcodeSchema(String xcodeSchema) { this.xcodeSchema = xcodeSchema; } @CheckForNull public String getArchiveDir() { return archiveDir; } @DataBoundSetter public void setArchiveDir(String archiveDir) { this.archiveDir = archiveDir; } @CheckForNull public String getDevelopmentTeamName() { return developmentTeamName; } @DataBoundSetter public void setDevelopmentTeamName(String developmentTeamName) { this.developmentTeamName = developmentTeamName; } @CheckForNull public String getDevelopmentTeamID() { return developmentTeamID; } @DataBoundSetter public void setDevelopmentTeamID(String developmentTeamID) { this.developmentTeamID = developmentTeamID; } @CheckForNull public String getIpaName() { return ipaName; } @DataBoundSetter public void setIpaName(String ipaName) { this.ipaName = ipaName; } @CheckForNull public String getIpaOutputDirectory() { return ipaOutputDirectory; } @DataBoundSetter public void setIpaOutputDirectory(String ipaOutputDirectory) { this.ipaOutputDirectory = ipaOutputDirectory; } @CheckForNull public String getIpaExportMethod() { return ipaExportMethod; } @DataBoundSetter public void setIpaExportMethod(String ipaExportMethod) { this.ipaExportMethod = ipaExportMethod; } @Deprecated public Boolean getManualSigning() { return ( signingMethod == null || signingMethod.equals("manual") ); } @Deprecated @DataBoundSetter public void setManualSigning(Boolean manualSigning) { this.signingMethod = BooleanUtils.isTrue(manualSigning) ? "manual" : "automatic"; } @CheckForNull public String getSigningMethod() { return signingMethod == null ? "automatic" : signingMethod; } @DataBoundSetter public void setSigningMethod(String signingMethod) { this.signingMethod = signingMethod; } @CheckForNull public ArrayList getProvisioningProfiles() { return provisioningProfiles; } @DataBoundSetter public void setProvisioningProfiles(ArrayList provisioningProfiles) { this.provisioningProfiles = provisioningProfiles; } @CheckForNull public String getXcodeName() { return xcodeName; } @DataBoundSetter public void setXcodeName(String xcodeName) { this.xcodeName = xcodeName; } public Boolean getUploadBitcode() { return uploadBitcode; } @DataBoundSetter public void setUploadBitcode(Boolean uploadBitcode) { this.uploadBitcode = uploadBitcode; } public Boolean getUploadSymbols() { return uploadSymbols; } @DataBoundSetter public void setUploadSymbols(Boolean uploadSymbols) { this.uploadSymbols = uploadSymbols; } public Boolean getCompileBitcode() { return compileBitcode; } @DataBoundSetter public void setCompileBitcode(Boolean compileBitcode) { this.compileBitcode = compileBitcode; } @CheckForNull public String getThinning() { return thinning; } @DataBoundSetter public void setThinning(String thinning) { this.thinning = thinning; } public Boolean getPackResourcesAsset() { return embedOnDemandResourcesAssetPacksInBundle; } @DataBoundSetter public void setPackResourcesAsset(Boolean packResourcesAsset) { this.embedOnDemandResourcesAssetPacksInBundle = packResourcesAsset; } @CheckForNull public String getResourcesAssetURL() { return onDemandResourcesAssetPacksBaseURL; } @DataBoundSetter public void setResourcesAssetURL(String resourcesAssetURL) { this.onDemandResourcesAssetPacksBaseURL = resourcesAssetURL; } @CheckForNull public String getAppURL() { return appURL; } @DataBoundSetter public void setAppURL(String appURL) { this.appURL = appURL; } @CheckForNull public String getDisplayImageURL() { return displayImageURL; } @DataBoundSetter public void setDisplayImageURL(String displayImageURL) { this.displayImageURL = displayImageURL; } @CheckForNull public String getFullSizeImageURL() { return fullSizeImageURL; } @DataBoundSetter public void setFullSizeImageURL(String fullSizeImageURL) { this.fullSizeImageURL = fullSizeImageURL; } @CheckForNull public String getAssetPackManifestURL() { return assetPackManifestURL; } @DataBoundSetter public void setAssetPackManifestURL(String assetPackManifestURL) { this.assetPackManifestURL = assetPackManifestURL; } public Boolean getStripSwiftSymbols() { return stripSwiftSymbols == null ? Boolean.valueOf(true) : stripSwiftSymbols; } @DataBoundSetter public void setStripSwiftSymbols(Boolean stripSwiftSymbols) { this.stripSwiftSymbols = stripSwiftSymbols; } public Boolean getCopyProvisioningProfile() { return copyProvisioningProfile == null ? Boolean.valueOf(true) : copyProvisioningProfile; } @DataBoundSetter public void setCopyProvisioningProfile(Boolean copyProvisioningProfile) { this.copyProvisioningProfile = copyProvisioningProfile; } @CheckForNull public String getKeychainId() { return keychainId; } @DataBoundSetter public void setKeychainId(String keychainId) { this.keychainId = keychainId; } @DataBoundConstructor public ExportIpa() { } @Deprecated public ExportIpa(String xcodeProjectPath, String xcodeProjectFile, Boolean unlockKeychain, String keychainName, String keychainPath, String keychainPwd, String symRoot, String xcodeWorkspaceFile, String xcodeSchema, String archiveDir, String developmentTeamName, String developmentTeamID, String ipaName, String ipaOutputDirectory, String ipaExportMethod, String signingMethod, ArrayList provisioningProfiles, String xcodeName, Boolean uploadBitcode, Boolean uploadSymbols, Boolean compileBitcode, String thinning, Boolean packResourcesAsset, String resourcesAssetURL, String appURL, String displayImageURL, String fullSizeImageURL, String assetPackManifestURL) { this(); this.xcodeProjectPath = xcodeProjectPath; this.xcodeProjectFile = xcodeProjectFile; this.keychainName = keychainName; this.xcodeWorkspaceFile = xcodeWorkspaceFile; this.xcodeSchema = xcodeSchema; this.developmentTeamName = developmentTeamName; this.developmentTeamID = developmentTeamID; this.unlockKeychain = unlockKeychain; this.keychainPath = keychainPath; this.keychainPwd = Secret.fromString(keychainPwd); this.symRoot = symRoot; this.archiveDir = archiveDir; this.ipaName = ipaName; this.ipaOutputDirectory = ipaOutputDirectory; this.ipaExportMethod = ipaExportMethod; this.signingMethod = signingMethod; this.provisioningProfiles = provisioningProfiles; this.xcodeName = xcodeName; this.uploadBitcode = uploadBitcode; this.uploadSymbols = uploadSymbols; this.compileBitcode = compileBitcode; this.thinning = thinning; this.embedOnDemandResourcesAssetPacksInBundle = packResourcesAsset; this.onDemandResourcesAssetPacksBaseURL = resourcesAssetURL; this.appURL = appURL; this.displayImageURL = displayImageURL; this.fullSizeImageURL = fullSizeImageURL; this.assetPackManifestURL = assetPackManifestURL; this.stripSwiftSymbols = true; } @Override public void perform(Run build, FilePath filePath, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { _perform(build, filePath, launcher, build.getEnvironment(listener), listener); } @SuppressFBWarnings("DM_DEFAULT_ENCODING") private boolean _perform(Run build, FilePath filePath, Launcher launcher, EnvVars envs, TaskListener listener) throws InterruptedException, IOException { XCodeBuilder builder = new XCodeBuilder(true, false, true, null, false, false, null, null, null, xcodeProjectPath, xcodeProjectFile, null, null, null, unlockKeychain, keychainName, keychainPath, Secret.toString(keychainPwd), symRoot, xcodeWorkspaceFile, xcodeSchema, archiveDir, developmentTeamName, developmentTeamID, false, ipaName, false, ipaOutputDirectory, false, null, null, false, ipaExportMethod, signingMethod, provisioningProfiles, xcodeName, uploadBitcode, uploadSymbols, compileBitcode, thinning, embedOnDemandResourcesAssetPacksInBundle, onDemandResourcesAssetPacksBaseURL, appURL, displayImageURL, fullSizeImageURL, assetPackManifestURL); builder.setStripSwiftSymbols(stripSwiftSymbols); builder.setCopyProvisioningProfile(copyProvisioningProfile); builder.setSkipBuildStep(true); builder.setKeychainId(keychainId); builder.perform(build, filePath, launcher, listener); return true; } public GlobalConfigurationImpl getGlobalConfiguration() { return getDescriptor().getGlobalConfiguration(); } @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } @Extension @Symbol("exportIpa") public static final class DescriptorImpl extends BuildStepDescriptor { GlobalConfigurationImpl globalConfiguration; @Override public String getDisplayName() { return Messages.ExportIpa_ExportIpa(); } public DescriptorImpl() { load(); } @SuppressFBWarnings("UWF_UNWRITTEN_FIELD") @Inject void setGlobalConfiguration(GlobalConfigurationImpl c) { this.globalConfiguration = c; } public GlobalConfigurationImpl getGlobalConfiguration() { return globalConfiguration; } @Override public boolean isApplicable(Class aClass) { return true; } public String getUUID() { return "" + UUID.randomUUID().getMostSignificantBits(); } public FormValidation doCheckArchiveDir(@QueryParameter String value) { if ( value.isEmpty() ) { return FormValidation.error(Messages.ExportIpa_NeedToSpecifyArchiveLocation()); } return FormValidation.ok(); } public FormValidation doCheckResourcesAssetURL(@QueryParameter String value, @QueryParameter Boolean packResourcesAsset) { if ( StringUtils.isEmpty(value) && !packResourcesAsset ) { return FormValidation.error(Messages.XCodeBuilder_NeedOnDemandResourcesURL()); } return FormValidation.ok(); } public FormValidation doCheckIpaExportMethod(@QueryParameter String value) { if ( !ArrayUtils.contains(VALID_IPA_EXPORT_METHODS, value) ) { String validMethodsMsg = StringUtils.join(VALID_IPA_EXPORT_METHODS, ", "); return FormValidation.error(Messages.XCodeBuilder_IpaExportMethodMuestBeOneOfTheFollowing(validMethodsMsg)); } return FormValidation.ok(); } public FormValidation doCheckXcodeWorkspaceFile(@QueryParameter String value, @QueryParameter String xcodeSchema, @QueryParameter String target) { if ( !StringUtils.isEmpty(value) ) { if ( !StringUtils.isEmpty(target) ) { return FormValidation.error(Messages.XCodeBuilder_WorkspaceAndTargetCantSpecifySameTime()); } if ( StringUtils.isEmpty(xcodeSchema) ) { return FormValidation.error(Messages.XCodeBuilder_SpecifyWorkspaceAlsoSetScheme()); } } return FormValidation.ok(); } public FormValidation doCheckXcodeSchema(@QueryParameter String value, @QueryParameter Boolean generateArchive, @QueryParameter String xcodeWorkspaceFile, @QueryParameter String target) { if ( !StringUtils.isEmpty(value) ) { if ( !StringUtils.isEmpty(target) ) { return FormValidation.error(Messages.XCodeBuilder_SchemeAndTargetCantSpecifySameTime()); } } else { if ( !StringUtils.isEmpty(xcodeWorkspaceFile) ) { return FormValidation.error(Messages.XCodeBuilder_SpecifyWorkspaceAlsoSetScheme()); } return FormValidation.warning(Messages.XCodeBuilder_NeedSchema()); } return FormValidation.ok(); } } } ================================================ FILE: src/main/java/au/com/rayh/GlobalConfigurationImpl.java ================================================ /* * The MIT License * * Copyright (c) 2013 Maur�cio Hanika * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh; import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import hudson.Extension; import hudson.model.AbstractProject; import hudson.model.AutoCompletionCandidates; import hudson.util.FormValidation; import jenkins.model.GlobalConfiguration; import java.io.IOException; import java.util.ArrayList; import java.util.logging.Logger; import edu.umd.cs.findbugs.annotations.CheckForNull; import javax.servlet.ServletException; /** * Stores global configuration for XCode. * * @since 1.4 */ @Extension public final class GlobalConfigurationImpl extends GlobalConfiguration { private static final Logger LOGGER = Logger.getLogger(GlobalConfigurationImpl.class.getName()); @CheckForNull private String xcodebuildPath = "/usr/bin/xcodebuild"; @CheckForNull private String xcrunPath = "/usr/bin/xcrun"; @CheckForNull private String agvtoolPath = "/usr/bin/agvtool"; // No one uses defaultKeychain. @Deprecated @CheckForNull private String defaultKeychain = ""; @Deprecated @CheckForNull private ArrayList keychains = new ArrayList<>(); @Deprecated @CheckForNull private ArrayList teams = new ArrayList<>(); @DataBoundSetter public void setXcodebuildPath(String xcodebuildPath) { this.xcodebuildPath = xcodebuildPath; } @CheckForNull public String getXcodebuildPath() { return xcodebuildPath; } @DataBoundSetter public void setXcrunPath(String xcrunPath) { this.xcrunPath = xcrunPath; } @CheckForNull public String getXcrunPath() { return xcrunPath; } @DataBoundSetter public void setAgvtoolPath(String agvtoolPath) { this.agvtoolPath = agvtoolPath; } @CheckForNull public String getAgvtoolPath() { return agvtoolPath; } @Deprecated @DataBoundSetter public void setDefaultKeychain(String defaultKeychain) { this.defaultKeychain = defaultKeychain; } @Deprecated @CheckForNull public String getDefaultKeychain() { return defaultKeychain; } @Deprecated @DataBoundSetter public void setKeychains(ArrayList keychains) { this.keychains = keychains; } @Deprecated public ArrayList getKeychains() { return keychains == null ? keychains : new ArrayList(); } @Deprecated @DataBoundSetter public void setTeams(ArrayList teams) { this.teams = teams; } @Deprecated public ArrayList getTeams() { return teams; } @DataBoundConstructor public GlobalConfigurationImpl() { super(); load(); LOGGER.fine("[Xcode] Default constructor: " + getKeychains().size()); } @Deprecated public GlobalConfigurationImpl(String xcodebuildPath, String xcrunPath, String agvtoolPath, String defaultKeychain, ArrayList keychains, ArrayList teams) { this(); this.setXcodebuildPath(xcodebuildPath); this.setXcrunPath(xcrunPath); this.setAgvtoolPath(agvtoolPath); this.setDefaultKeychain(defaultKeychain); this.setKeychains(keychains); this.setTeams(teams); LOGGER.fine("[Xcode] DataBoundConstructor: keychains.size " + keychains.size()); if(teams != null) { LOGGER.fine("[Xcode] DataBoundConstructor: teams.size " + teams.size()); } } @Deprecated public GlobalConfigurationImpl(String xcodebuildPath, String xcrunPath, String agvtoolPath, String defaultKeychain, ArrayList keychains) { this(xcodebuildPath, xcrunPath, agvtoolPath, defaultKeychain, keychains, null); } public FormValidation doCheckXcodebuildPath(@QueryParameter String value) throws IOException, ServletException { if (StringUtils.isEmpty(value)) { return FormValidation.error(Messages.XCodeBuilder_xcodebuildPathNotSet()); } else { // TODO: check that the file exists (and if an agent is used ?) } return FormValidation.ok(); } public FormValidation doCheckAgvtoolPath(@QueryParameter String value) throws IOException, ServletException { if (StringUtils.isEmpty(value)) { return FormValidation.error(Messages.XCodeBuilder_agvtoolPathNotSet()); } else { // TODO: check that the file exists (and if an agent is used ?) } return FormValidation.ok(); } public FormValidation doCheckXcrunPath(@QueryParameter String value) throws IOException, ServletException { if (StringUtils.isEmpty(value)) { return FormValidation.error(Messages.XCodeBuilder_xcrunPathNotSet()); } else { // TODO: check that the file exists (and if an agent is used ?) } return FormValidation.ok(); } /* Useless method that doesn't make sense. public FormValidation doCheckDefaultKeychain(@QueryParameter String value) throws IOException, ServletException { if (!StringUtils.isEmpty(value)) { Boolean foundKeychain = false; for (Keychain k : getKeychains()) { if (k.getKeychainName().equals(value)) { foundKeychain = true; break; } } if (!foundKeychain) { return FormValidation.error(Messages.OSXKeychainBuildWrapper_invalidDefaultKeychainName(value)); } } return FormValidation.ok(); } */ public AutoCompletionCandidates doAutoCompleteDefaultKeychain(@QueryParameter String value) { AutoCompletionCandidates c = new AutoCompletionCandidates(); for (Keychain keychain : getKeychains()) { if (keychain.getKeychainName().toLowerCase().startsWith(value.toLowerCase())) { c.add(keychain.getKeychainName()); } } return c; } public boolean isApplicable(Class aClass) { // indicates that this builder can be used with all kinds of project types return true; } @Override public String getDisplayName() { return Messages.XCodeBuilder_xcode(); } @Override public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { req.bindJSON(this, formData); setKeychains(new ArrayList<>(req.bindParametersToList(Keychain.class, "keychain."))); setTeams(new ArrayList<>(req.bindParametersToList(Team.class, "team."))); save(); return super.configure(req, formData); } } ================================================ FILE: src/main/java/au/com/rayh/InfoPlist.java ================================================ package au.com.rayh; import hudson.FilePath; //import org.kohsuke.stapler.DataBoundConstructor; public class InfoPlist { private FilePath infoPlistFile; private String cfBundleIdentifier; private String cfBundleVersion; private String cfBundleShortVersionString; InfoPlist() { infoPlistFile = null; cfBundleIdentifier = null; cfBundleVersion = null; cfBundleShortVersionString = null; } //@DataBoundConstructor InfoPlist(FilePath infoPlistFile, String cfBundleIdentifier, String cfBundleVersion, String cfBundleShortVersionString) { this.infoPlistFile = infoPlistFile; this.cfBundleIdentifier = cfBundleIdentifier; this.cfBundleVersion = cfBundleVersion; this.cfBundleShortVersionString = cfBundleShortVersionString; } public FilePath getInfoPlistFile() { return this.infoPlistFile; } public void setInfoPlistFile(FilePath infoPlistFile) { this.infoPlistFile = infoPlistFile; } public String getCfBundleIdentifier() { return this.cfBundleIdentifier; } public void setCfBundleIdentifier(String cfBundleIdentifier) { this.cfBundleIdentifier = cfBundleIdentifier; } public String getCfBundleVersion() { return this.cfBundleVersion; } public void setCfBundleVersion(String cfBundleVersion) { this.cfBundleVersion = cfBundleVersion; } public String getCfBundleShortVersionString() { return this.cfBundleShortVersionString; } public void setCfBundleShortVersionString(String cfBundleShortVersionString) { this.cfBundleShortVersionString = cfBundleShortVersionString; } } ================================================ FILE: src/main/java/au/com/rayh/JenkinsXCodeBuildOutputParser.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package au.com.rayh; import hudson.FilePath; import hudson.Functions; import hudson.model.TaskListener; import java.io.BufferedOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.GregorianCalendar; import org.apache.commons.lang.StringUtils; /** * * @author ray */ public class JenkinsXCodeBuildOutputParser extends XCodeBuildOutputParser { protected TaskListener buildListener; private FilePath testReportsDir; private OutputStream logFileOutputStream; private boolean ignoreTestResults; public JenkinsXCodeBuildOutputParser(FilePath workspace, TaskListener buildListener) throws IOException, InterruptedException { super(); this.buildListener = buildListener; this.captureOutputStream = new LineBasedFilterOutputStream(); this.consoleLog = true; this.logFileOutputStream = null; this.ignoreTestResults = false; testReportsDir = workspace.child("test-reports"); testReportsDir.mkdirs(); } public void setConsoleLog(boolean consoleLog) { this.consoleLog = consoleLog; } public void setIgnoreTestResults(boolean ignoreTestResults) { this.ignoreTestResults = ignoreTestResults; } public void setLogfilePath(final FilePath buildDirectory, final String logfileOutputDirectory) throws IOException, InterruptedException { // Remove buildDirectory.exists() && buildDirectory.isDirectory() from condition. // Because If Generate archive is not specified, directory was not created. if(!StringUtils.isEmpty(logfileOutputDirectory)) { // Fix not to use timestamp for log file name. (Use "xcodebuild.log" as a fixed file name) // Because using a timestamp as a filename, No way to know it with a script etc. FilePath logFilePath = buildDirectory.child(logfileOutputDirectory); // clean Directory if(logFilePath.exists()) { logFilePath.deleteRecursive(); } // Create if non-existent if (!logFilePath.exists()) { logFilePath.mkdirs(); } logFileOutputStream = new BufferedOutputStream(logFilePath.child("xcodebuild.log").write(),1024*512); } } public void closeLogfile() throws IOException { if(logFileOutputStream != null) { logFileOutputStream.flush(); logFileOutputStream.close(); logFileOutputStream = null; } } public class LineBasedFilterOutputStream extends FilterOutputStream { StringBuilder buffer = new StringBuilder(); public LineBasedFilterOutputStream() { super(buildListener.getLogger()); } @Override public void write(int b) throws IOException { if ( !ignoreTestResults ) { if((char)b == '\n') { try { handleLine(buffer.toString()); buffer = new StringBuilder(); } catch(Exception e) { // Very fugly Functions.printStackTrace(e, buildListener.fatalError(e.getMessage())); throw new IOException(e); } } else { buffer.append((char)b); } } if(consoleLog) { super.write(b); } if(logFileOutputStream != null) { logFileOutputStream.write(b); } } @Override public void close() throws IOException { if(logFileOutputStream != null) { logFileOutputStream.flush(); logFileOutputStream.close(); logFileOutputStream = null; } super.close(); } } @Override protected OutputStream outputForSuite() throws IOException, InterruptedException { return testReportsDir.child("TEST-" + currentTestSuite.getName() + ".xml").write(); } } ================================================ FILE: src/main/java/au/com/rayh/Keychain.java ================================================ package au.com.rayh; import hudson.util.Secret; import org.apache.commons.lang.StringUtils; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; public class Keychain { private String keychainName; private String keychainPath; private Secret keychainPassword; private Boolean inSearchPath; public Keychain() { } @Deprecated @DataBoundConstructor public Keychain(String keychainName, String keychainPath, String keychainPassword, Boolean inSearchPath) { this.keychainName = keychainName; this.keychainPath = keychainPath; this.keychainPassword = Secret.fromString(keychainPassword); this.inSearchPath = inSearchPath; } public String getKeychainName() { return keychainName; } @DataBoundSetter public void setKeychainName(String keychainName) { this.keychainName = keychainName; } public String getKeychainPath() { return keychainPath; } @DataBoundSetter public void setKeychainPath(String keychainPath) { this.keychainPath = keychainPath; } public Secret getKeychainPassword() { return keychainPassword; } @DataBoundSetter public void setKeychainPassword(Secret keychainPassword) { this.keychainPassword = keychainPassword; } public Boolean isInSearchPath() { return inSearchPath; } @DataBoundSetter public void setInSearchPath(Boolean inSearchPath) { this.inSearchPath = inSearchPath; } } ================================================ FILE: src/main/java/au/com/rayh/KeychainPasswordAndPath.java ================================================ /* * The MIT License * * Copyright (c) 2011-2012, CloudBees, Inc., Stephen Connolly. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh; import com.cloudbees.plugins.credentials.CredentialsNameProvider; import com.cloudbees.plugins.credentials.NameWith; import com.cloudbees.plugins.credentials.common.PasswordCredentials; import com.cloudbees.plugins.credentials.common.StandardCredentials; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Util; import hudson.util.Secret; import java.io.IOException; /** * Credentials that have an ID, description and macOS Keychain password and path. * */ @NameWith(value = KeychainPasswordAndPath.NameProvider.class, priority = 32) public interface KeychainPasswordAndPath extends StandardCredentials, PasswordCredentials { /** * * */ Secret getPassword(); String getKeychainPath(); boolean isInSearchPath(); String getInSearchPath(); /** * Our name provider. * * @since 2.0.12 */ public static class NameProvider extends CredentialsNameProvider { /** * {@inheritDoc} */ @NonNull @Override public String getName(@NonNull KeychainPasswordAndPath c) { String description = Util.fixEmptyAndTrim(c.getDescription()); return c.getKeychainPath() + (description != null ? " (" + description + ")" : ""); } } } ================================================ FILE: src/main/java/au/com/rayh/KeychainPasswordAndPathBinding.java ================================================ /* * The MIT License * * Copyright (c) 2016, CloudBees, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * */ package au.com.rayh; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.Run; import hudson.model.TaskListener; import org.apache.commons.lang.StringUtils; import org.jenkinsci.plugins.credentialsbinding.BindingDescriptor; import org.jenkinsci.plugins.credentialsbinding.MultiBinding; import org.kohsuke.stapler.DataBoundConstructor; import edu.umd.cs.findbugs.annotations.NonNull; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * @author Kazuhide Takahashi */ public class KeychainPasswordAndPathBinding extends MultiBinding { public final static String DEFAULT_KEYCHAIN_PATH_VARIABLE_NAME = "KEYCHAIN_PATH"; private final static String DEFAULT_PASSWORD_VARIABLE_NAME = "PASSWORD"; private final static String DEFAULT_IN_SEARCH_PATH_VARIABLE_NAME = "IN_SEARCH_PATH"; @NonNull private final String keychainPathVariable; @NonNull private final String passwordVariable; @NonNull private final String inSearchPathVariable; /** * * @param keychainPathVariable if {@code null}, {@value DEFAULT_KEYCHAIN_PATH_VARIABLE_NAME} will be used. * @param passwordVariable if {@code null}, {@value DEFAULT_PASSWORD_VARIABLE_NAME} will be used. * @param inSearchPathVariable if {@code null}, {@value DEFAULT_IN_SEARCH_PATH_VARIABLE_NAME} will be used. * @param credentialsId identifier which should be referenced when accessing the credentials from a job/pipeline. */ @DataBoundConstructor public KeychainPasswordAndPathBinding(@Nullable String keychainPathVariable, @Nullable String passwordVariable, @Nullable String inSearchPathVariable, String credentialsId) { super(credentialsId); this.keychainPathVariable = StringUtils.defaultIfBlank(keychainPathVariable, DEFAULT_KEYCHAIN_PATH_VARIABLE_NAME); this.passwordVariable = StringUtils.defaultIfBlank(passwordVariable, DEFAULT_PASSWORD_VARIABLE_NAME); this.inSearchPathVariable = StringUtils.defaultIfBlank(inSearchPathVariable, DEFAULT_IN_SEARCH_PATH_VARIABLE_NAME); } @NonNull public String getKeychainPathVariable() { return keychainPathVariable; } @NonNull public String getPasswordVariable() { return passwordVariable; } @NonNull public String getInSearchPathVariable() { return inSearchPathVariable; } @Override protected Class type() { return KeychainPasswordAndPath.class; } @Override public MultiEnvironment bind(@NonNull Run build, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException, InterruptedException { KeychainPasswordAndPath credential = getCredentials(build); Map m = new HashMap(); m.put(keychainPathVariable, credential.getKeychainPath()); m.put(passwordVariable, credential.getPassword().getPlainText()); m.put(inSearchPathVariable, credential.getInSearchPath()); return new MultiEnvironment(m); } @Override public Set variables() { return new HashSet(Arrays.asList(keychainPathVariable, passwordVariable, inSearchPathVariable)); } @Extension public static class DescriptorImpl extends BindingDescriptor { @Override protected Class type() { return KeychainPasswordAndPath.class; } @Override public String getDisplayName() { return Messages.KeychainPasswordAndPath_DisplayName(); } } } ================================================ FILE: src/main/java/au/com/rayh/KeychainPasswordAndPathImpl.java ================================================ /* * The MIT License * * Copyright (c) 2011-2016, CloudBees, Inc., Stephen Connolly. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh; import com.cloudbees.plugins.credentials.CredentialsDescriptor; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.domains.DomainRequirement; import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.Util; import hudson.security.ACL; import hudson.util.Secret; import org.kohsuke.stapler.DataBoundConstructor; import com.cloudbees.plugins.credentials.CredentialsScope; import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials; import org.kohsuke.stapler.DataBoundSetter; import java.util.Collections; import java.util.List; /** * */ @SuppressWarnings("unused") // read resolved by extension plugins public class KeychainPasswordAndPathImpl extends BaseStandardCredentials implements KeychainPasswordAndPath { /** * The Keychain path. */ @NonNull private String keychainPath; /** * The password. */ @NonNull private Secret password; /** * The flag for keychain in search path. */ private String inSearchPath; /** * Constructor. * * @param scope the credentials scope * @param id the ID or {@code null} to generate a new one. * @param description the description. * @param keychainPath the Keychain path. * @param password the password. * @param inSearchPath flag for keychain in search path. */ @DataBoundConstructor @SuppressWarnings("unused") // by stapler public KeychainPasswordAndPathImpl(@CheckForNull CredentialsScope scope, @CheckForNull String id, @CheckForNull String description, @CheckForNull String keychainPath, @CheckForNull String password, @CheckForNull String inSearchPath) { super(scope, id, description); this.keychainPath = Util.fixNull(keychainPath); this.password = Secret.fromString(password); this.inSearchPath = inSearchPath; } /** * {@inheritDoc} */ public Secret getPassword() { return password; } @DataBoundSetter public void setPassword(Secret password) { this.password = password; } /** * macOS Keychain path. * @return full path for macOS keychain */ @NonNull public String getKeychainPath() { return keychainPath; } @DataBoundSetter public void setKeychainPath(String keychainPath) { this.keychainPath = keychainPath; } /** * Add keychain to search path. * @return inSearchPath by String. */ public String getInSearchPath() { return inSearchPath; } @DataBoundSetter public void setInSearchPath(String inSearchPath) { this.inSearchPath = inSearchPath; } /** * Add keyc hain to search path. * @return check is inSearchPath equals "true". */ public boolean isInSearchPath() { return inSearchPath == null ? false : inSearchPath.equals("true"); } /** * {@inheritDoc} */ @Extension public static class DescriptorImpl extends BaseStandardCredentialsDescriptor { /** * {@inheritDoc} */ @Override public String getDisplayName() { return Messages.KeychainPasswordAndPath_DisplayName(); } /* * {@inheritDoc} * @Override public String getIconClassName() { return "icon-credentials"; } */ } public static List getAllKeycainInfo() { return CredentialsProvider.lookupCredentials(KeychainPasswordAndPathImpl.class, (hudson.model.Item)null, ACL.SYSTEM, Collections.emptyList()); } } ================================================ FILE: src/main/java/au/com/rayh/KeychainUnlockStep.java ================================================ package au.com.rayh; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.AbortException; import hudson.EnvVars; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.*; import hudson.security.ACL; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.util.ArgumentListBuilder; import hudson.util.FormValidation; import hudson.util.Secret; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.CheckForNull; import javax.inject.Inject; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Collections; import java.util.UUID; /** * Installs {@link DeveloperProfile} into the current slave and unlocks its keychain * in preparation for the signing that uses it. * * TODO: destroy identity in the end. * * @author Kohsuke Kawaguchi */ @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") public class KeychainUnlockStep extends Builder implements SimpleBuildStep { @Deprecated @CheckForNull private String keychainName; @CheckForNull private String keychainId; @CheckForNull private String keychainPath; @CheckForNull private Secret keychainPwd; @Deprecated @CheckForNull public String getKeychainName() { return keychainName; } @CheckForNull public String getKeychainId() { return keychainId; } @Deprecated @DataBoundSetter public void setKeychainName(String keychainName) { this.keychainName = keychainName; } @DataBoundSetter public void setKeychainId(String keychainId) { this.keychainId = keychainId; } @CheckForNull public String getKeychainPath() { return keychainPath; } @DataBoundSetter public void setKeychainPath(String keychainPath) { this.keychainPath = keychainPath; } @CheckForNull public Secret getKeychainPwd() { return keychainPwd; } @DataBoundSetter public void setKeychainPwd(Secret keychainPwd) { this.keychainPwd = keychainPwd; } @DataBoundConstructor public KeychainUnlockStep() { } @Deprecated public KeychainUnlockStep(String keychainName) { this(); this.keychainName = keychainName; } @Override public void perform(@NonNull Run run, @NonNull FilePath workspace, @NonNull Launcher launcher, @NonNull TaskListener listener) throws InterruptedException, IOException { EnvVars envs = run.getEnvironment(listener); String _keychainId = envs.expand(this.keychainId); String _keychainName = envs.expand(this.keychainName); String _keychainPath; String _keychainPwd; if ( StringUtils.isNotEmpty(_keychainName) ) { // for backward compatibility listener.getLogger().println(Messages.XCodeBuilder_UseDeprecatedKeychainInfo()); Keychain keychain = getKeychain(_keychainName); if ( keychain == null ) { throw new AbortException(Messages.DeveloperProfileLoader_NoKeychainInfoConfigured()); } else { _keychainPath = envs.expand(keychain.getKeychainPath()); _keychainPwd = envs.expand(Secret.toString(keychain.getKeychainPassword())); } } else if ( StringUtils.isNotEmpty(_keychainId) ) { // for backward compatibility KeychainPasswordAndPath keychain = getKeychainPasswordAndPath(run.getParent(), _keychainId); if ( keychain == null ) { throw new AbortException(Messages.DeveloperProfileLoader_NoKeychainInfoConfigured()); } else { _keychainPath = envs.expand(keychain.getKeychainPath()); _keychainPwd = envs.expand(keychain.getPassword().getPlainText()); } } else { _keychainPath = envs.expand(this.keychainPath); _keychainPwd = envs.expand(Secret.toString(this.keychainPwd)); } ArgumentListBuilder args; args = new ArgumentListBuilder("security", "unlock-keychain"); args.add("-p").addMasked(_keychainPwd); args.add(_keychainPath); invoke(launcher, listener, args, "Failed to unlock keychain"); } @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { perform(build, build.getWorkspace(), launcher, listener); return true; } @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } public GlobalConfigurationImpl getGlobalConfiguration() { return getDescriptor().getGlobalConfiguration(); } public Keychain getKeychain(String keychainName) { if ( !StringUtils.isEmpty(keychainName) ) { for ( Keychain keychain : getGlobalConfiguration().getKeychains() ) { if ( keychain.getKeychainName().equals(keychainName) ) return keychain; } } if ( !StringUtils.isEmpty(this.keychainPath) ) { Keychain newKeychain = new Keychain(); newKeychain.setKeychainPath(keychainPath); newKeychain.setKeychainPassword(this.keychainPwd); return newKeychain; } return null; } public KeychainPasswordAndPath getKeychainPasswordAndPath(Item context, String keychainId) { return (KeychainPasswordAndPath) CredentialsMatchers.firstOrNull( CredentialsProvider.lookupCredentials(KeychainPasswordAndPath.class, context, ACL.SYSTEM, Collections.EMPTY_LIST), CredentialsMatchers.withId(keychainId)); } private ByteArrayOutputStream invoke(Launcher launcher, TaskListener listener, ArgumentListBuilder args, String errorMessage) throws IOException, InterruptedException { ByteArrayOutputStream output = new ByteArrayOutputStream(); if (launcher.launch().cmds(args).stdout(output).join()!=0) { listener.getLogger().write(output.toByteArray()); throw new AbortException(errorMessage); } return output; } @Extension @Symbol("unlockMacOSKeychain") public static class DescriptorImpl extends BuildStepDescriptor { GlobalConfigurationImpl globalConfiguration; @SuppressFBWarnings("UWF_UNWRITTEN_FIELD") @Inject void setGlobalConfiguration(GlobalConfigurationImpl c) { this.globalConfiguration = c; } @Override public boolean isApplicable(Class jobType) { return true; } @Override public String getDisplayName() { return Messages.OSXKeychainUnclockStep_DisplayName(); } public GlobalConfigurationImpl getGlobalConfiguration() { return globalConfiguration; } public String getUUID() { return "" + UUID.randomUUID().getMostSignificantBits(); } public FormValidation doCheckKeychainPath(@QueryParameter String value, @QueryParameter String keychainName) { if ( StringUtils.isEmpty(keychainName) && StringUtils.isEmpty(value) ) { return FormValidation.error(Messages.DeveloperProfileLoader_MustSpecifyKeychainPath()); } return FormValidation.ok(); } public FormValidation doCheckKeychainPwd(@QueryParameter Secret value, @QueryParameter String keychainName) { if ( StringUtils.isEmpty(keychainName) && StringUtils.isEmpty(Secret.toString(value)) ) { return FormValidation.error(Messages.DeveloperProfileLoader_MustSpecifyKeychainPwd()); } return FormValidation.ok(); } } } ================================================ FILE: src/main/java/au/com/rayh/MobileProvisionParser.java ================================================ package au.com.rayh; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; /** * Created by ud10404 on 5/9/14. */ public class MobileProvisionParser { private List targets = new ArrayList<>(); private List configurations = new ArrayList<>(); private List schemes = new ArrayList<>(); public MobileProvisionParser(String xcodebuildListOutput) { if(xcodebuildListOutput == null) { return; } String [] lines = xcodebuildListOutput.split("\n"); List curList = null; for(String line : lines) { line = line.trim(); if (StringUtils.isEmpty(line)) { curList = null; } else if("Targets:".equals(line)) { curList = targets; } else if("Build Configurations:".equals(line)) { curList = configurations; } else if("Schemes:".equals(line)) { curList = schemes; } else if(curList != null) { curList.add(line); } } } public List getTargets() { return this.targets; } public List getConfigurations() { return this.configurations; } public List getSchemes() { return this.schemes; } } ================================================ FILE: src/main/java/au/com/rayh/ProjectScheme.java ================================================ package au.com.rayh; public class ProjectScheme { //public String parallelizeBuildables; //public String buildImplicitDependencies; //public String blueprintIdentifier; //public String buildForTesting; //public String buildForRunning; //public String buildForProfiling; //public String buildForArchiving; //public String buildForAnalyzing; //public String buildableIdentifier; //public String buildableName; public String blueprintName; public String referencedContainer; ProjectScheme() { //parallelizeBuildables = null; //buildImplicitDependencies = null; //blueprintIdentifier = null; //buildForTesting = null; //buildForRunning = null; //buildForProfiling = null; //buildForArchiving = null; //buildForAnalyzing = null; //buildableIdentifier = null; //buildableName = null; blueprintName = null; referencedContainer = null; } } ================================================ FILE: src/main/java/au/com/rayh/ProjectTarget.java ================================================ package au.com.rayh; import java.util.HashMap; public class ProjectTarget { public String uuid; //public String name; public String productType; public String provisioningStyle; public String testTargetID; public String defaultConfigurationName; public HashMap buildConfiguration; ProjectTarget() { uuid = null; //name = null; productType = null; provisioningStyle = null; testTargetID = null; defaultConfigurationName = null; buildConfiguration = new HashMap(); } } ================================================ FILE: src/main/java/au/com/rayh/ProvisioningProfile.java ================================================ package au.com.rayh; import org.kohsuke.stapler.DataBoundConstructor; import hudson.EnvVars; public class ProvisioningProfile { private static final String PLIST_FORMAT = "${APP_ID}${UUID}"; private String provisioningProfileAppId; private String provisioningProfileUUID; public ProvisioningProfile() { } @DataBoundConstructor public ProvisioningProfile(String provisioningProfileAppId, String provisioningProfileUUID) { this.provisioningProfileAppId = provisioningProfileAppId; this.provisioningProfileUUID = provisioningProfileUUID; } public String getProvisioningProfileAppId() { return provisioningProfileAppId; } public void setProvisioningProfileAppId(String provisioningProfileAppId) { this.provisioningProfileAppId = provisioningProfileAppId; } public String getProvisioningProfileUUID() { return provisioningProfileUUID; } public void setProvisioningProfileUUID(String provisioningProfileUUID) { this.provisioningProfileUUID = provisioningProfileUUID; } public String toPlist(EnvVars envs) { return PLIST_FORMAT.replace("${APP_ID}", envs.expand(provisioningProfileAppId)) .replace("${UUID}", envs.expand(provisioningProfileUUID)); } } ================================================ FILE: src/main/java/au/com/rayh/Team.java ================================================ package au.com.rayh; import org.kohsuke.stapler.DataBoundConstructor; public class Team { private String teamName; private String teamID; public Team() { } @DataBoundConstructor public Team(String teamName, String teamID) { this.teamName = teamName; this.teamID = teamID; } public String getTeamName() { return teamName; } public void setTeamName(String teamName) { this.teamName = teamName; } public String getTeamID() { return teamID; } public void setTeamID(String teamID) { this.teamID = teamID; } } ================================================ FILE: src/main/java/au/com/rayh/XCArchiveFileFilter.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package au.com.rayh; import java.io.File; import java.io.FileFilter; import java.io.Serializable; /** * @author lampietti */ public class XCArchiveFileFilter implements FileFilter, Serializable { public boolean accept(File pathname) { return pathname.isDirectory() && pathname.getName().endsWith(".xcarchive"); } } ================================================ FILE: src/main/java/au/com/rayh/XCodeAction.java ================================================ package au.com.rayh; import hudson.model.InvisibleAction; import org.kohsuke.stapler.DataBoundConstructor; /** * Simple Action for storing the build number * @author Reuben Bijl */ public class XCodeAction extends InvisibleAction { private String buildDescription; @DataBoundConstructor public XCodeAction(String buildDescription) { this.buildDescription = buildDescription; } public String getBuildDescription() { return buildDescription; } } ================================================ FILE: src/main/java/au/com/rayh/XCodeBuildNumberTokenMacro.java ================================================ package au.com.rayh; import hudson.Extension; import hudson.model.AbstractBuild; import hudson.model.TaskListener; import org.jenkinsci.plugins.tokenmacro.DataBoundTokenMacro; import org.jenkinsci.plugins.tokenmacro.MacroEvaluationException; import java.io.IOException; @Extension public class XCodeBuildNumberTokenMacro extends DataBoundTokenMacro { @Override public String evaluate(AbstractBuild context, TaskListener listener, String macroName) throws MacroEvaluationException, IOException, InterruptedException { XCodeAction a = context.getAction(XCodeAction.class); if(a == null){ return ""; } return a.getBuildDescription(); } @Override public boolean acceptsMacroName(String macroName) { return macroName.equals("XCODE_BUILD_NUMBER"); } } ================================================ FILE: src/main/java/au/com/rayh/XCodeBuildOutputParser.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh; import java.io.File; import java.io.FileOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import au.com.rayh.report.TestCase; import au.com.rayh.report.TestError; import au.com.rayh.report.TestFailure; import au.com.rayh.report.TestSuite; /** * Parse Xcode output and transform into JUnit-style xml test result files. * This utility class creates and manages a FilterOutputStream to parse the Xcode output to capture the * results of ocunit tests. * @author John Bito <jwbito@gmail.com> */ public class XCodeBuildOutputParser { private static DateFormat[] dateFormats = { new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") }; private static Pattern START_SUITE = Pattern.compile("Test Suite '([^\\/](?:\\.|[^'\\\\])*)'\\s+started at\\s+(.*)"); private static Pattern END_SUITE = Pattern.compile("Test Suite '([^\\/](?:\\.|[^'\\\\])*)'\\s+\\S+\\s+at\\s+(.*)."); private static Pattern START_TESTCASE = Pattern.compile("Test Case '-\\[(\\S+)\\s+(\\S+)\\]' started."); private static Pattern END_TESTCASE = Pattern.compile("Test Case '-\\[(\\S+)\\s+(\\S+)\\]' passed \\((.*) seconds\\)."); private static Pattern ERROR_TESTCASE = Pattern.compile("(.*): error: -\\[(\\S+)\\s+(\\S+)\\] : (.*)"); private static Pattern ERROR_UI_TESTCASE = Pattern.compile(".*?Assertion Failure: (.+:\\d+): (.*)"); private static Pattern FAILED_TESTCASE = Pattern.compile("Test Case '-\\[(\\S+)\\s+(\\S+)\\]' failed \\((\\S+) seconds\\)."); private static Pattern FAILED_WITH_EXIT_CODE = Pattern.compile("failed with exit code (\\d+)"); private static Pattern TERMINATING_EXCEPTION = Pattern.compile(".*\\*\\*\\* Terminating app due to uncaught exception '(\\S+)', reason: '(.+[^\\\\])'.*"); private File testReportsDir; protected OutputStream captureOutputStream; protected int exitCode; protected HashMap testSuitesHash = new HashMap(); protected TestSuite currentTestSuite = null; protected TestCase currentTestCase = null; protected boolean consoleLog; protected XCodeBuildOutputParser() { super(); } /** * Initalize the FilterOutputStream and prepare to generate the JUnit result files * @param workspace directory that will receive the result files * @param log the Xcode output stream that should be parsed */ public XCodeBuildOutputParser(File workspace, OutputStream log) { this(); this.captureOutputStream = new LineBasedFilterOutputStream(log); this.testReportsDir = workspace; this.consoleLog = true; } public class LineBasedFilterOutputStream extends FilterOutputStream { StringBuilder buffer = new StringBuilder(); public LineBasedFilterOutputStream(OutputStream log) { super(log); } @Override public void write(int b) throws IOException { super.write(b); if((char)b == '\n') { try { handleLine(buffer.toString()); buffer = new StringBuilder(); } catch(Exception e) { // Very fugly throw new IOException(e); } } else { buffer.append((char)b); } } } private Date parseDate(String text) throws ParseException { Date date; ParseException parseException; date = null; parseException = null; for (DateFormat dateFormat : dateFormats) { try { date = dateFormat.parse(text); break; } catch (ParseException exception) { parseException = exception; } } if ((date == null) && (parseException != null)) { throw parseException; } return date; } private void requireTestSuite() { if(testSuitesHash.size()==0) { throw new RuntimeException("Log statements out of sync: current test suite was empty"); } if(currentTestSuite==null) { throw new RuntimeException("Log statements out of sync: current test suite was null"); } } private void requireTestSuite(String name) { currentTestSuite = testSuitesHash.get(name); if(currentTestSuite==null) { // Swift String[] testSuites = name.split(Pattern.quote(".")); if ( testSuites.length == 2 ) { String xctestName = testSuites[0] + ".xctest"; String testSuite = testSuites[1]; if ( !testSuitesHash.containsKey(xctestName) ) { throw new RuntimeException("Log statements out of sync: current test suite '" + xctestName + "' not exists"); } currentTestSuite = testSuitesHash.get(testSuite); if ( currentTestSuite == null ) { throw new RuntimeException("Log statements out of sync: current test suite '" + testSuite + "' not exists"); } } } } private void requireTestCase(String name) { currentTestCase = currentTestSuite.getTestCasesHash().get(name); if(currentTestCase==null) { throw new RuntimeException("Log statements out of sync: current test case '" + currentTestSuite.getName() + "." + name + "' not exists"); } } private void writeTestReport() throws IOException, InterruptedException, JAXBException { try (OutputStream testReportOutputStream = outputForSuite()) { JAXBContext jaxbContext; Thread t = Thread.currentThread(); ClassLoader orig = t.getContextClassLoader(); t.setContextClassLoader(XCodeBuildOutputParser.class.getClassLoader()); try { jaxbContext = JAXBContext.newInstance(TestSuite.class); } finally { t.setContextClassLoader(orig); } Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.marshal(currentTestSuite, testReportOutputStream); } } protected OutputStream outputForSuite() throws IOException, InterruptedException { return new FileOutputStream(new File(testReportsDir, "TEST-" + currentTestSuite.getName() + ".xml")); } protected void handleLine(String line) throws ParseException, IOException, InterruptedException, JAXBException { Matcher m = START_SUITE.matcher(line); if(m.matches()) { if (testSuitesHash.isEmpty()) { consoleLog = true; } String suite_name = m.group(1); if ( m.group(1).endsWith(".xctest") ) { suite_name = suite_name.replaceAll("-", "_"); } currentTestSuite = new TestSuite(InetAddress.getLocalHost().getHostName(), m.group(1), parseDate(m.group(2))); testSuitesHash.put(suite_name, currentTestSuite); return; } m = END_SUITE.matcher(line); if(m.matches()) { String suite_name = m.group(1); if ( m.group(1).endsWith(".xctest") ) { suite_name = suite_name.replaceAll("-", "_"); } requireTestSuite(suite_name); currentTestSuite.setEndTime(parseDate(m.group(2))); writeTestReport(); testSuitesHash.remove(suite_name); currentTestSuite = null; if ( testSuitesHash.size() == 1 ) { // If the last test suitev in nhash is Unknown, process it and exit. currentTestSuite = testSuitesHash.get("UnknownSuite"); if ( currentTestSuite != null ) { currentTestSuite.setEndTime(parseDate(m.group(2))); writeTestReport(); testSuitesHash.remove(suite_name); currentTestSuite = null; } } if (testSuitesHash.isEmpty()) { consoleLog = false; } return; } m = START_TESTCASE.matcher(line); if(m.matches()) { requireTestSuite(m.group(1)); currentTestCase = new TestCase(m.group(1), m.group(2)); currentTestSuite.getTestCasesHash().put(m.group(2), currentTestCase); return; } m = END_TESTCASE.matcher(line); if(m.matches()) { requireTestSuite(m.group(1)); requireTestCase(m.group(2)); currentTestCase.setTime(Float.parseFloat(m.group(3))); currentTestSuite.getTestCases().add(currentTestCase); currentTestSuite.addTest(); // Actually, I think that the test case should be closed and deleted here. // In case the error is reported late without synchronization. //currentTestSuite.getTestCasesHash().remove(m.group(2)); currentTestCase = null; return; } m = ERROR_TESTCASE.matcher(line); if(m.matches()) { String errorLocation = m.group(1); String testSuite = m.group(2); String testCase = m.group(3); String errorMessage = m.group(4); requireTestSuite(testSuite); requireTestCase(testCase); TestFailure failure = new TestFailure(errorMessage, errorLocation); currentTestCase.getFailures().add(failure); return; } // If the test result is returned asynchronously, there is a possibility // that in this case the target test can not be decided and information // is recorded in the wrong place. m = ERROR_UI_TESTCASE.matcher(line); if(m.matches()) { String errorLocation = m.group(1); String errorMessage = m.group(2); TestFailure failure = new TestFailure(errorMessage, errorLocation); if ( currentTestSuite == null ) { currentTestSuite = testSuitesHash.get("UnknownSuite"); if ( currentTestSuite == null ) { currentTestSuite = new TestSuite(InetAddress.getLocalHost().getHostName(), "UnknownSuite", new Date()); testSuitesHash.put("UnknownSuite", currentTestSuite); } } if ( currentTestCase == null ) { currentTestCase = currentTestSuite.getTestCasesHash().get("UnknownTestCase"); if ( currentTestCase == null ) { currentTestCase = new TestCase(currentTestSuite.getName(), "UnknownTestCase"); currentTestSuite.getTestCasesHash().put("UnknownTestCase", currentTestCase); currentTestSuite.getTestCases().add(currentTestCase); currentTestSuite.addTest(); } } currentTestCase.getFailures().add(failure); return; } m = FAILED_TESTCASE.matcher(line); if(m.matches()) { requireTestSuite(m.group(1)); requireTestCase(m.group(2)); currentTestSuite.addTest(); currentTestSuite.addFailure(); currentTestCase.setTime(Float.parseFloat(m.group(3))); currentTestSuite.getTestCases().add(currentTestCase); //currentTestSuite.getTestCasesHash().remove(m.group(2)); currentTestCase = null; return; } m = FAILED_WITH_EXIT_CODE.matcher(line); if(m.matches()) { exitCode = Integer.parseInt(m.group(1)); return; } if(line.matches("BUILD FAILED") || line.matches("\\*\\* TEST FAILED \\*\\*")) { exitCode = -1; } m = TERMINATING_EXCEPTION.matcher(line); if(m.matches()) { exitCode = -1; requireTestSuite(); if (currentTestCase != null) { TestError error = new TestError(m.group(2), m.group(1)); currentTestCase.getErrors().add(error); currentTestSuite.getTestCases().add(currentTestCase); currentTestSuite.addTest(); currentTestSuite.addError(); //currentTestSuite.getTestCasesHash().remove(currentTestCase.getName()); currentTestCase = null; } writeTestReport(); currentTestSuite = null; } } public OutputStream getOutputStream() { return captureOutputStream; } public int getExitCode() { return exitCode; } } ================================================ FILE: src/main/java/au/com/rayh/XCodeBuilder.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.AbortException; import hudson.EnvVars; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.model.*; import hudson.security.ACL; import hudson.util.FormValidation; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.Builder; import hudson.util.CopyOnWriteList; import hudson.util.QuotedStringTokenizer; import hudson.plugins.xcode.XcodeInstallation; import hudson.util.Secret; import jenkins.tasks.SimpleBuildStep; import org.jenkinsci.Symbol; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.jenkinsci.plugins.tokenmacro.MacroEvaluationException; import org.jenkinsci.plugins.tokenmacro.TokenMacro; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import jenkins.model.Jenkins; import javax.inject.Inject; import edu.umd.cs.findbugs.annotations.CheckForNull; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectStreamException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.regex.Pattern; import java.util.UUID; import java.util.Collection; import java.util.concurrent.TimeUnit; import com.dd.plist.NSDictionary; import com.dd.plist.PropertyListParser; /** * @author Ray Hilton */ @SuppressFBWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE") public class XCodeBuilder extends Builder implements SimpleBuildStep { private static final int SIGTERM = 143; private static final String DEVELOPMENT_ENV = "Development"; private static final String PRODUCTION_ENV = "Production"; private static final String DEV_SIGNING_CERTIFICATE_SELECTOR = "iOS Developer"; private static final String DIST_SIGNING_CERTIFICATE_SELECTOR = "iOS Distribution"; private static final String[] VALID_IPA_EXPORT_METHODS = { "development", "ad-hoc", "enterprise", "app-store" }; /** * @since 1.0 */ @CheckForNull private Boolean cleanBeforeBuild; /** * @since 1.3 */ @CheckForNull private Boolean cleanTestReports; /** * @since 1.0 */ @CheckForNull private String configuration; /** * @since 1.0 */ @CheckForNull private String target; /** * @since 1.0 */ @CheckForNull private String sdk; /** * @since 1.1 */ @CheckForNull private String symRoot; /** * @since 1.2 */ @CheckForNull private String buildDir; /** * @since 1.0 */ @CheckForNull private String xcodeProjectPath; /** * @since 1.0 */ @CheckForNull private String xcodeProjectFile; /** * @since 1.3 */ @CheckForNull private String xcodebuildArguments; /** * @since 1.2 */ @CheckForNull private String xcodeSchema; /** * @since 1.2 */ @CheckForNull private String xcodeWorkspaceFile; /** * @since 1.0 */ @CheckForNull private String cfBundleVersionValue; /** * @since 1.0 */ @CheckForNull private String cfBundleShortVersionStringValue; /** * @since 1.0 */ @CheckForNull private Boolean buildIpa; /** * @since 1.4.12 */ @CheckForNull private String ipaExportMethod; /** * @since 1.0 */ @CheckForNull private Boolean generateArchive; /** * @since 2.0.1 */ @CheckForNull private Boolean noConsoleLog; /** * @since 2.0.1 */ @CheckForNull private String logfileOutputDirectory; /** * @since 1.5 **/ @CheckForNull private Boolean unlockKeychain; /** * @since 1.4 */ @Deprecated @CheckForNull private String keychainName; /** * @since 2.0.12 */ @CheckForNull private String keychainId; /** * @since 1.0 */ @CheckForNull private String keychainPath; /** * @since 1.0 */ @CheckForNull private Secret keychainPwd; /** * @since 1.4.12 */ @CheckForNull private String developmentTeamName; /** * @since 1.4.12 */ @CheckForNull private String developmentTeamID; /** * @since 1.4 */ @CheckForNull private Boolean allowFailingBuildResults; /** * @since 1.4 */ @CheckForNull private String ipaName; /** * @since 1.4 */ @CheckForNull private String ipaOutputDirectory; /** * @since 1.4 */ @CheckForNull private Boolean provideApplicationVersion; /** * @since 1.4 */ @CheckForNull private Boolean changeBundleID; /** * @since 1.4 */ @CheckForNull private String bundleID; /** * @since 1.4 */ @CheckForNull private String bundleIDInfoPlistPath; /** * @since 1.4 */ @CheckForNull private Boolean interpretTargetAsRegEx; /** * @deprecated 2.0.3 * @CheckForNull private String ipaManifestPlistUrl; */ /** * @deprecated 2.0.7 * @CheckForNull private Boolean manualSigning; */ /** * @since 2.0.7 */ @CheckForNull private String signingMethod; /** * @since 2.0.1 */ @CheckForNull private ArrayList provisioningProfiles; /* * @since 2.0.3 */ @CheckForNull private String xcodeName; /* * @since 2.0.3 */ @CheckForNull private Boolean uploadBitcode; /* * @since 2.0.3 */ @CheckForNull private Boolean uploadSymbols; /* * @since 2.0.3 */ @CheckForNull private Boolean compileBitcode; /* * @since 2.0.3 */ @CheckForNull private String thinning; /* * @since 2.0.3 */ @CheckForNull private Boolean embedOnDemandResourcesAssetPacksInBundle; /* * @since 2.0.3 */ @CheckForNull private String onDemandResourcesAssetPacksBaseURL; /* * @since 2.0.3 */ @CheckForNull private String appURL; /* * @since 2.0.3 */ @CheckForNull private String displayImageURL; /* * @since 2.0.3 */ @CheckForNull private String fullSizeImageURL; /* * @since 2.0.3 */ @CheckForNull private String assetPackManifestURL; /** * @since 2.0.3 */ @CheckForNull private Boolean skipBuildStep; /** * @since 2.0.5 */ @CheckForNull private Boolean stripSwiftSymbols; /** * @since 2.0.7 */ @CheckForNull private Boolean copyProvisioningProfile; /** * @since 2.0.9 */ @CheckForNull private Boolean useLegacyBuildSystem; /** * @since 2.0.11 */ @CheckForNull private Boolean ignoreTestResults; /** * @since 2.0.11 */ @CheckForNull private String resultBundlePath; /** * @since 2.0.11 */ @CheckForNull private Boolean cleanResultBundlePath; public Boolean getCleanBeforeBuild() { return cleanBeforeBuild == null ? Boolean.valueOf(true) : cleanBeforeBuild; } @DataBoundSetter public void setCleanBeforeBuild(Boolean cleanBeforeBuild) { this.cleanBeforeBuild = cleanBeforeBuild; } public Boolean getCleanTestReports() { return cleanTestReports == null ? Boolean.valueOf(false) : cleanTestReports; } @DataBoundSetter public void setCleanTestReports(Boolean cleanTestReports) { this.cleanTestReports = cleanTestReports; } @CheckForNull public String getConfiguration() { return configuration; } @DataBoundSetter public void setConfiguration(String configuration) { this.configuration = configuration; } @CheckForNull public String getTarget() { return target; } @DataBoundSetter public void setTarget(String target) { this.target = target; } @CheckForNull public String getSdk() { return sdk; } @DataBoundSetter public void setSdk(String sdk) { this.sdk = sdk; } @CheckForNull public String getSymRoot() { return symRoot; } @DataBoundSetter public void setSymRoot(String symRoot) { this.symRoot = symRoot; } @CheckForNull public String getBuildDir() { return buildDir; } @DataBoundSetter public void setBuildDir(String buildDir) { this.buildDir = buildDir; } @CheckForNull public String getXcodeProjectPath() { return xcodeProjectPath; } @DataBoundSetter public void setXcodeProjectPath(String xcodeProjectPath) { this.xcodeProjectPath = xcodeProjectPath; } @CheckForNull public String getXcodeProjectFile() { return xcodeProjectFile; } @DataBoundSetter public void setXcodeProjectFile(String xcodeProjectFile) { this.xcodeProjectFile = xcodeProjectFile; } @CheckForNull public String getXcodebuildArguments() { return xcodebuildArguments; } @DataBoundSetter public void setXcodebuildArguments(String xcodebuildArguments) { this.xcodebuildArguments = xcodebuildArguments; } @CheckForNull public String getXcodeSchema() { return xcodeSchema; } @DataBoundSetter public void setXcodeSchema(String xcodeSchema) { this.xcodeSchema = xcodeSchema; } @CheckForNull public String getXcodeWorkspaceFile() { return xcodeWorkspaceFile; } @DataBoundSetter public void setXcodeWorkspaceFile(String xcodeWorkspaceFile) { this.xcodeWorkspaceFile = xcodeWorkspaceFile; } @CheckForNull public String getCfBundleVersionValue() { return cfBundleVersionValue; } @DataBoundSetter public void setCfBundleVersionValue(String cfBundleVersionValue) { this.cfBundleVersionValue = cfBundleVersionValue; } @CheckForNull public String getCfBundleShortVersionStringValue() { return cfBundleShortVersionStringValue; } @DataBoundSetter public void setCfBundleShortVersionStringValue(String cfBundleShortVersionStringValue) { this.cfBundleShortVersionStringValue = cfBundleShortVersionStringValue; } public Boolean getBuildIpa() { return buildIpa == null ? Boolean.valueOf(false) : buildIpa; } @DataBoundSetter public void setBuildIpa(Boolean buildIpa) { this.buildIpa = buildIpa; } public String getIpaExportMethod() { return ipaExportMethod == null ? "app-store" : ipaExportMethod; } @DataBoundSetter public void setIpaExportMethod(String ipaExportMethod) { this.ipaExportMethod = ipaExportMethod; } public Boolean getGenerateArchive() { return generateArchive == null ? Boolean.valueOf(false) : generateArchive; } @DataBoundSetter public void setGenerateArchive(Boolean generateArchive) { this.generateArchive = generateArchive; } public Boolean getNoConsoleLog() { return noConsoleLog == null ? Boolean.valueOf(false) : noConsoleLog; } @DataBoundSetter public void setNoConsoleLog(Boolean noConsoleLog) { this.noConsoleLog = noConsoleLog; } @CheckForNull public String getLogfileOutputDirectory() { return logfileOutputDirectory; } @DataBoundSetter public void setLogfileOutputDirectory(String logfileOutputDirectory) { this.logfileOutputDirectory = logfileOutputDirectory; } public Boolean getUnlockKeychain() { return unlockKeychain == null ? Boolean.valueOf(false) : unlockKeychain; } @DataBoundSetter public void setUnlockKeychain(Boolean unlockKeychain) { this.unlockKeychain = unlockKeychain; } @Deprecated @CheckForNull public String getKeychainName() { return keychainName; } @CheckForNull public String getKeychainId() { return keychainId; } @Deprecated @DataBoundSetter public void setKeychainName(String keychainName) { this.keychainName = keychainName; } @DataBoundSetter public void setKeychainId(String keychainId) { this.keychainId = keychainId; } @CheckForNull public String getKeychainPath() { return keychainPath; } @DataBoundSetter public void setKeychainPath(String keychainPath) { this.keychainPath = keychainPath; } @CheckForNull public Secret getKeychainPwd() { return keychainPwd; } @DataBoundSetter public void setKeychainPwd(Secret keychainPwd) { this.keychainPwd = keychainPwd; } @CheckForNull public String getDevelopmentTeamName() { return developmentTeamName; } @DataBoundSetter public void setDevelopmentTeamName(String developmentTeamName) { this.developmentTeamName = developmentTeamName; } @CheckForNull public String getDevelopmentTeamID() { return developmentTeamID; } @DataBoundSetter public void setDevelopmentTeamID(String developmentTeamID) { this.developmentTeamID = developmentTeamID; } public Boolean getAllowFailingBuildResults() { return allowFailingBuildResults == null ? Boolean.valueOf(false) : allowFailingBuildResults; } @DataBoundSetter public void setAllowFailingBuildResults(Boolean allowFailingBuildResults) { this.allowFailingBuildResults = allowFailingBuildResults; } @CheckForNull public String getIpaName() { return ipaName; } @DataBoundSetter public void setIpaName(String ipaName) { this.ipaName = ipaName; } @CheckForNull public String getIpaOutputDirectory() { return ipaOutputDirectory; } @DataBoundSetter public void setIpaOutputDirectory(String ipaOutputDirectory) { this.ipaOutputDirectory = ipaOutputDirectory; } public Boolean getProvideApplicationVersion() { return provideApplicationVersion == null ? Boolean.valueOf(false) : provideApplicationVersion; } @DataBoundSetter public void setProvideApplicationVersion(Boolean provideApplicationVersion) { this.provideApplicationVersion = provideApplicationVersion; } public Boolean getChangeBundleID() { return changeBundleID == null ? Boolean.valueOf(false) : changeBundleID; } @DataBoundSetter public void setChangeBundleID(Boolean changeBundleID) { this.changeBundleID = changeBundleID; } @CheckForNull public String getBundleID() { return bundleID; } @DataBoundSetter public void setBundleID(String bundleID) { this.bundleID = bundleID; } @CheckForNull public String getBundleIDInfoPlistPath() { return bundleIDInfoPlistPath; } @DataBoundSetter public void setBundleIDInfoPlistPath(String bundleIDInfoPlistPath) { this.bundleIDInfoPlistPath = bundleIDInfoPlistPath; } public Boolean getInterpretTargetAsRegEx() { return interpretTargetAsRegEx == null ? Boolean.valueOf(false) : interpretTargetAsRegEx; } @DataBoundSetter public void setInterpretTargetAsRegEx(Boolean interpretTargetAsRegEx) { this.interpretTargetAsRegEx = interpretTargetAsRegEx; } @Deprecated public Boolean getManualSigning() { return ( signingMethod == null || signingMethod.equals("manual") ); } @Deprecated @DataBoundSetter public void setManualSigning(Boolean manualSigning) { this.signingMethod = BooleanUtils.isTrue(manualSigning) ? "manual" : "automatic"; } public String getSigningMethod() { return signingMethod == null ? "automatic" : signingMethod; } @DataBoundSetter public void setSigningMethod(String signingMethod) { this.signingMethod = signingMethod; } @CheckForNull public ArrayList getProvisioningProfiles() { return provisioningProfiles; } @DataBoundSetter public void setProvisioningProfiles(ArrayList provisioningProfiles) { this.provisioningProfiles = provisioningProfiles; } @CheckForNull public String getXcodeName() { return xcodeName; } @DataBoundSetter public void setXcodeName(String xcodeName) { this.xcodeName = xcodeName; } public Boolean getUploadBitcode() { return uploadBitcode == null ? Boolean.valueOf(true) : uploadBitcode; } @DataBoundSetter public void setUploadBitcode(Boolean uploadBitcode) { this.uploadBitcode = uploadBitcode; } public Boolean getUploadSymbols() { return uploadSymbols == null ? Boolean.valueOf(true) : uploadSymbols; } @DataBoundSetter public void setUploadSymbols(Boolean uploadSymbols) { this.uploadSymbols = uploadSymbols; } public Boolean getCompileBitcode() { return compileBitcode == null ? Boolean.valueOf(true) : compileBitcode; } @DataBoundSetter public void setCompileBitcode(Boolean compileBitcode) { this.compileBitcode = compileBitcode; } @CheckForNull public String getThinning() { return thinning; } @DataBoundSetter public void setThinning(String thinning) { this.thinning = thinning; } public Boolean getAssetPacksInBundle() { return embedOnDemandResourcesAssetPacksInBundle == null ? Boolean.valueOf(true) : embedOnDemandResourcesAssetPacksInBundle; } @DataBoundSetter public void setAssetPacksInBundle(Boolean assetPacksInBundle) { this.embedOnDemandResourcesAssetPacksInBundle = assetPacksInBundle; } @CheckForNull public String getAssetPacksBaseURL() { return onDemandResourcesAssetPacksBaseURL; } @DataBoundSetter public void setAssetPacksBaseURL(String assetPacksBaseURL) { this.onDemandResourcesAssetPacksBaseURL = assetPacksBaseURL; } @CheckForNull public String getAppURL() { return appURL; } @DataBoundSetter public void setAppURL(String appURL) { this.appURL = appURL; } @CheckForNull public String getDisplayImageURL() { return displayImageURL; } @DataBoundSetter public void setDisplayImageURL(String displayImageURL) { this.displayImageURL = displayImageURL; } @CheckForNull public String getFullSizeImageURL() { return fullSizeImageURL; } @DataBoundSetter public void setFullSizeImageURL(String fullSizeImageURL) { this.fullSizeImageURL = fullSizeImageURL; } @CheckForNull public String getAssetPackManifestURL() { return assetPackManifestURL; } @DataBoundSetter public void setAssetPackManifestURL(String assetPackManifestURL) { this.assetPackManifestURL = assetPackManifestURL; } public Boolean getStripSwiftSymbols() { return stripSwiftSymbols == null ? Boolean.valueOf(true) : stripSwiftSymbols; } @DataBoundSetter public void setStripSwiftSymbols(Boolean stripSwiftSymbols) { this.stripSwiftSymbols = stripSwiftSymbols; } public Boolean getCopyProvisioningProfile() { return copyProvisioningProfile == null ? Boolean.valueOf(true) : copyProvisioningProfile; } @DataBoundSetter public void setCopyProvisioningProfile(Boolean copyProvisioningProfile) { this.copyProvisioningProfile = copyProvisioningProfile; } public Boolean getUseLegacyBuildSystem() { return useLegacyBuildSystem == null ? Boolean.valueOf(false) : useLegacyBuildSystem; } @DataBoundSetter public void setUseLegacyBuildSystem(Boolean useLegacyBuildSystem) { this.useLegacyBuildSystem = useLegacyBuildSystem; } public Boolean getIgnoreTestResults() { return ignoreTestResults == null ? Boolean.valueOf(false) : ignoreTestResults; } @DataBoundSetter public void setIgnoreTestResults(Boolean ignoreTestResults) { this.ignoreTestResults = ignoreTestResults; } public String getResultBundlePath() { return resultBundlePath; } @DataBoundSetter public void setResultBundlePath(String resultBundlePath) { this.resultBundlePath = resultBundlePath; } @DataBoundSetter public void setCleanResultBundlePath(Boolean cleanResultBundlePath) { this.cleanResultBundlePath = cleanResultBundlePath; } public Boolean getCleanResultBundlePath() { return cleanResultBundlePath == null ? Boolean.valueOf(true) : cleanResultBundlePath; } // Internally. public void setSkipBuildStep(Boolean skipBuildStep) { this.skipBuildStep = skipBuildStep; } // Fields in config.jelly must match the parameter names in the "DataBoundConstructor" @DataBoundConstructor public XCodeBuilder() { this.skipBuildStep = Boolean.valueOf(false); } @Deprecated public XCodeBuilder(Boolean buildIpa, Boolean generateArchive, Boolean noConsoleLog, String logfileOutputDirectory, Boolean cleanBeforeBuild, Boolean cleanTestReports, String configuration, String target, String sdk, String xcodeProjectPath, String xcodeProjectFile, String xcodebuildArguments, String cfBundleVersionValue, String cfBundleShortVersionStringValue, Boolean unlockKeychain, String keychainName, String keychainPath, String keychainPwd, String symRoot, String xcodeWorkspaceFile, String xcodeSchema, String buildDir, String developmentTeamName, String developmentTeamID, Boolean allowFailingBuildResults, String ipaName, Boolean provideApplicationVersion, String ipaOutputDirectory, Boolean changeBundleID, String bundleID, String bundleIDInfoPlistPath, Boolean interpretTargetAsRegEx, String ipaExportMethod, String signingMethod, ArrayList provisioningProfiles, String xcodeName, Boolean uploadBitcode, Boolean uploadSymbols, Boolean compileBitcode, String thinning, Boolean embedOnDemandResourcesAssetPacksInBundle, String onDemandResourcesAssetPacksBaseURL, String appURL, String displayImageURL, String fullSizeImageURL, String assetPackManifestURL) { this(); this.buildIpa = buildIpa; this.generateArchive = generateArchive; this.noConsoleLog = noConsoleLog; this.logfileOutputDirectory = logfileOutputDirectory; this.sdk = sdk; this.target = target; this.cleanBeforeBuild = cleanBeforeBuild; this.cleanTestReports = cleanTestReports; this.configuration = configuration; this.xcodeProjectPath = xcodeProjectPath; this.xcodeProjectFile = xcodeProjectFile; this.xcodebuildArguments = xcodebuildArguments; this.keychainName = keychainName; this.xcodeWorkspaceFile = xcodeWorkspaceFile; this.xcodeSchema = xcodeSchema; this.developmentTeamName = developmentTeamName; this.developmentTeamID = developmentTeamID; this.cfBundleVersionValue = cfBundleVersionValue; this.cfBundleShortVersionStringValue = cfBundleShortVersionStringValue; this.unlockKeychain = unlockKeychain; this.keychainPath = keychainPath; this.keychainPwd = Secret.fromString(keychainPwd); this.symRoot = symRoot; this.buildDir = buildDir; this.allowFailingBuildResults = allowFailingBuildResults; this.ipaName = ipaName; this.ipaOutputDirectory = ipaOutputDirectory; this.provideApplicationVersion = provideApplicationVersion; this.changeBundleID = changeBundleID; this.bundleID = bundleID; this.bundleIDInfoPlistPath = bundleIDInfoPlistPath; this.interpretTargetAsRegEx = interpretTargetAsRegEx; //this.ipaManifestPlistUrl = null; this.ipaExportMethod = ipaExportMethod; this.signingMethod = signingMethod; this.provisioningProfiles = provisioningProfiles; this.xcodeName = xcodeName; this.uploadBitcode = uploadBitcode; this.uploadSymbols = uploadSymbols; this.compileBitcode = compileBitcode; this.thinning = thinning; this.embedOnDemandResourcesAssetPacksInBundle = embedOnDemandResourcesAssetPacksInBundle; this.onDemandResourcesAssetPacksBaseURL = onDemandResourcesAssetPacksBaseURL; this.appURL = appURL; this.displayImageURL = displayImageURL; this.fullSizeImageURL = fullSizeImageURL; this.assetPackManifestURL = assetPackManifestURL; this.stripSwiftSymbols = Boolean.valueOf(true); this.skipBuildStep = Boolean.valueOf(false); } @Deprecated public XCodeBuilder(Boolean buildIpa, Boolean generateArchive, Boolean noConsoleLog, String logfileOutputDirectory, Boolean cleanBeforeBuild, Boolean cleanTestReports, String configuration, String target, String sdk, String xcodeProjectPath, String xcodeProjectFile, String xcodebuildArguments, String cfBundleVersionValue, String cfBundleShortVersionStringValue, Boolean unlockKeychain, String keychainName, String keychainPath, String keychainPwd, String symRoot, String xcodeWorkspaceFile, String xcodeSchema, String buildDir, String developmentTeamName, String developmentTeamID, Boolean allowFailingBuildResults, String ipaName, Boolean provideApplicationVersion, String ipaOutputDirectory, Boolean changeBundleID, String bundleID, String bundleIDInfoPlistPath, String ipaManifestPlistUrl, Boolean interpretTargetAsRegEx, String ipaExportMethod, String signingMethod, ArrayList provisioningProfiles, String xcodeName) { this(buildIpa, generateArchive, noConsoleLog, logfileOutputDirectory, cleanBeforeBuild, cleanTestReports, configuration, target, sdk, xcodeProjectPath, xcodeProjectFile, xcodebuildArguments, cfBundleVersionValue, cfBundleShortVersionStringValue, unlockKeychain, keychainName, keychainPath, keychainPwd, symRoot, xcodeWorkspaceFile, xcodeSchema, buildDir, developmentTeamName, developmentTeamID, allowFailingBuildResults, ipaName, provideApplicationVersion, ipaOutputDirectory, changeBundleID, bundleID, bundleIDInfoPlistPath, interpretTargetAsRegEx, ipaExportMethod, signingMethod, provisioningProfiles, xcodeName, true, true, true, null, false, null, ipaManifestPlistUrl, null, null, null); } @Deprecated public XCodeBuilder(Boolean buildIpa, Boolean generateArchive, Boolean noConsoleLog, String logfileOutputDirectory, Boolean cleanBeforeBuild, Boolean cleanTestReports, String configuration, String target, String sdk, String xcodeProjectPath, String xcodeProjectFile, String xcodebuildArguments, String cfBundleVersionValue, String cfBundleShortVersionStringValue, Boolean unlockKeychain, String keychainName, String keychainPath, String keychainPwd, String symRoot, String xcodeWorkspaceFile, String xcodeSchema, String buildDir, String developmentTeamName, String developmentTeamID, Boolean allowFailingBuildResults, String ipaName, Boolean provideApplicationVersion, String ipaOutputDirectory, Boolean changeBundleID, String bundleID, String bundleIDInfoPlistPath, String ipaManifestPlistUrl, Boolean interpretTargetAsRegEx, String ipaExportMethod, Boolean manualSigning, ArrayListprovisioningProfiles) { this(buildIpa, generateArchive, noConsoleLog, logfileOutputDirectory, cleanBeforeBuild, cleanTestReports, configuration, target, sdk, xcodeProjectPath, xcodeProjectFile, xcodebuildArguments, cfBundleVersionValue, cfBundleShortVersionStringValue, unlockKeychain, keychainName, keychainPath, keychainPwd, symRoot, xcodeWorkspaceFile, xcodeSchema, buildDir, developmentTeamName, developmentTeamID, allowFailingBuildResults, ipaName, provideApplicationVersion, ipaOutputDirectory, changeBundleID, bundleID, bundleIDInfoPlistPath, ipaManifestPlistUrl, interpretTargetAsRegEx, ipaExportMethod, (manualSigning ? "manual" : "automatic"), provisioningProfiles, null); } @Deprecated public XCodeBuilder(Boolean buildIpa, Boolean generateArchive, Boolean noConsoleLog, String logfileOutputDirectory, Boolean cleanBeforeBuild, Boolean cleanTestReports, String configuration, String target, String sdk, String xcodeProjectPath, String xcodeProjectFile, String xcodebuildArguments, String cfBundleVersionValue, String cfBundleShortVersionStringValue, Boolean unlockKeychain, String keychainName, String keychainPath, String keychainPwd, String symRoot, String xcodeWorkspaceFile, String xcodeSchema, String buildDir, String developmentTeamName, String developmentTeamID, Boolean allowFailingBuildResults, String ipaName, Boolean provideApplicationVersion, String ipaOutputDirectory, Boolean changeBundleID, String bundleID, String bundleIDInfoPlistPath, String ipaManifestPlistUrl, Boolean interpretTargetAsRegEx, String ipaExportMethod) { this(buildIpa, generateArchive, noConsoleLog, logfileOutputDirectory, cleanBeforeBuild, cleanTestReports, configuration, target, sdk, xcodeProjectPath, xcodeProjectFile, xcodebuildArguments, cfBundleVersionValue, cfBundleShortVersionStringValue, unlockKeychain, keychainName, keychainPath, keychainPwd, symRoot, xcodeWorkspaceFile, xcodeSchema, buildDir, developmentTeamName, developmentTeamID, allowFailingBuildResults, ipaName, provideApplicationVersion, ipaOutputDirectory, changeBundleID, bundleID, bundleIDInfoPlistPath, ipaManifestPlistUrl, interpretTargetAsRegEx, ipaExportMethod, true, null); } @Deprecated public XCodeBuilder(Boolean buildIpa, Boolean generateArchive, Boolean cleanBeforeBuild, Boolean cleanTestReports, String configuration, String target, String sdk, String xcodeProjectPath, String xcodeProjectFile, String xcodebuildArguments, String cfBundleVersionValue, String cfBundleShortVersionStringValue, Boolean unlockKeychain, String keychainName, String keychainPath, String keychainPwd, String symRoot, String xcodeWorkspaceFile, String xcodeSchema, String buildDir, String developmentTeamName, String developmentTeamID, Boolean allowFailingBuildResults, String ipaName, Boolean provideApplicationVersion, String ipaOutputDirectory, Boolean changeBundleID, String bundleID, String bundleIDInfoPlistPath, String ipaManifestPlistUrl, Boolean interpretTargetAsRegEx, String ipaExportMethod) { this(buildIpa, generateArchive, false, null, cleanBeforeBuild, cleanTestReports, configuration, target, sdk, xcodeProjectPath, xcodeProjectFile, xcodebuildArguments, cfBundleVersionValue, cfBundleShortVersionStringValue, unlockKeychain, keychainName, keychainPath, keychainPwd, symRoot, xcodeWorkspaceFile, xcodeSchema, buildDir, developmentTeamName, developmentTeamID, allowFailingBuildResults, ipaName, provideApplicationVersion, ipaOutputDirectory, changeBundleID, bundleID, bundleIDInfoPlistPath, ipaManifestPlistUrl, interpretTargetAsRegEx, ipaExportMethod); } @Deprecated public XCodeBuilder(Boolean buildIpa, Boolean generateArchive, Boolean cleanBeforeBuild, Boolean cleanTestReports, String configuration, String target, String sdk, String xcodeProjectPath, String xcodeProjectFile, String xcodebuildArguments, String embeddedProfileFile, String cfBundleVersionValue, String cfBundleShortVersionStringValue, Boolean unlockKeychain, String keychainName, String keychainPath, String keychainPwd, String symRoot, String xcodeWorkspaceFile, String xcodeSchema, String configurationBuildDir, String codeSigningIdentity, Boolean allowFailingBuildResults, String ipaName, Boolean provideApplicationVersion, String ipaOutputDirectory, Boolean changeBundleID, String bundleID, String bundleIDInfoPlistPath, String ipaManifestPlistUrl, Boolean interpretTargetAsRegEx, Boolean signIpaOnXcrun) { this(buildIpa, generateArchive, false, null, cleanBeforeBuild, cleanTestReports, configuration, target, sdk, xcodeProjectPath, xcodeProjectFile, xcodebuildArguments, cfBundleVersionValue, cfBundleShortVersionStringValue, unlockKeychain, keychainName, keychainPath, keychainPwd, symRoot, xcodeWorkspaceFile, xcodeSchema, configurationBuildDir, "", "", allowFailingBuildResults, ipaName, provideApplicationVersion, ipaOutputDirectory, changeBundleID, bundleID, bundleIDInfoPlistPath, ipaManifestPlistUrl, interpretTargetAsRegEx, "ad-hoc"); } @SuppressWarnings("unused") private Object readResolve() throws ObjectStreamException { if (provideApplicationVersion == null) { if (!StringUtils.isEmpty(cfBundleVersionValue) || !StringUtils.isEmpty(cfBundleShortVersionStringValue)) { provideApplicationVersion = Boolean.valueOf(true); } } return this; } @Override public void perform(Run build, FilePath filePath, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { boolean result = _perform(build, filePath, launcher, build.getEnvironment(listener), listener); if (!result) { throw new AbortException(Messages.XCodeBuilder_AbortXcodeBuildFailed()); } } @Override public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { return _perform(build, build.getWorkspace(), launcher, build.getEnvironment(listener), listener); } @SuppressFBWarnings("DM_DEFAULT_ENCODING") private boolean _perform(Run build, FilePath projectRoot, Launcher launcher, EnvVars envs, TaskListener listener) throws InterruptedException, IOException { // check that the configured tools exist if (!new FilePath(projectRoot.getChannel(), getGlobalConfiguration().getXcodebuildPath()).exists()) { listener.fatalError(Messages.XCodeBuilder_xcodebuildNotFound(getGlobalConfiguration().getXcodebuildPath())); return false; } if (!new FilePath(projectRoot.getChannel(), getGlobalConfiguration().getAgvtoolPath()).exists()) { listener.fatalError(Messages.XCodeBuilder_avgtoolNotFound(getGlobalConfiguration().getAgvtoolPath())); return false; } // Start expanding all string variables in parameters // NOTE: we currently use variable shadowing to avoid having to rewrite all code (and break pull requests), this will be cleaned up at later stage. String configuration = envs.expand(this.configuration); String target = envs.expand(this.target); String sdk = envs.expand(this.sdk); String symRoot = envs.expand(this.symRoot); String buildDir = envs.expand(this.buildDir); String xcodeProjectPath = envs.expand(this.xcodeProjectPath); String xcodeProjectFile = envs.expand(this.xcodeProjectFile); String xcodebuildArguments = envs.expand(this.xcodebuildArguments); String xcodeSchema = envs.expand(this.xcodeSchema); String xcodeWorkspaceFile = envs.expand(this.xcodeWorkspaceFile); String cfBundleVersionValue = envs.expand(this.cfBundleVersionValue); String cfBundleShortVersionStringValue = envs.expand(this.cfBundleShortVersionStringValue); String ipaName = envs.expand(this.ipaName); String ipaOutputDirectory = envs.expand(this.ipaOutputDirectory); String bundleID = envs.expand(this.bundleID); String bundleIDInfoPlistPath = envs.expand(this.bundleIDInfoPlistPath); //String ipaManifestPlistUrl = envs.expand(this.ipaManifestPlistUrl); String ipaExportMethod = envs.expand(this.ipaExportMethod); String thinning = envs.expand(this.thinning); String onDemandResourcesAssetPacksBaseURL = envs.expand(this.onDemandResourcesAssetPacksBaseURL); String appURL = envs.expand(this.appURL); String displayImageURL = envs.expand(this.displayImageURL); String fullSizeImageURL = envs.expand(this.fullSizeImageURL); String assetPackManifestURL = envs.expand(this.assetPackManifestURL); // End expanding all string variables in parameters // Set the working directory if (!StringUtils.isEmpty(xcodeProjectPath)) { projectRoot = projectRoot.child(xcodeProjectPath); } listener.getLogger().println(Messages.XCodeBuilder_workingDir(projectRoot)); if (!StringUtils.isEmpty(this.xcodeName)) { Jenkins jenkinsInstance = Jenkins.getInstance(); XcodeInstallation.DescriptorImpl descriptor = (XcodeInstallation.DescriptorImpl)jenkinsInstance.getDescriptor(XcodeInstallation.class); XcodeInstallation[] installations = descriptor.getInstallations(); if ( installations != null ) { for ( XcodeInstallation installation : installations ) { if ( installation.getName().equals(this.xcodeName) ) { envs.put("DEVELOPER_DIR", installation.getHome()); listener.getLogger().println(Messages.XCodeBuilder_XcodeToolsDir(installation.getHome())); break; } } } } // Infer as best we can the build platform String buildPlatform = "iphoneos"; if (!StringUtils.isEmpty(sdk)) { if (StringUtils.contains(sdk.toLowerCase(), "iphonesimulator")) { // Building for the simulator buildPlatform = "iphonesimulator"; } } // Set the build directory and the symRoot // String symRootValue = null; if (!StringUtils.isEmpty(symRoot)) { try { // If not empty we use the Token Expansion to replace it // https://wiki.jenkins-ci.org/display/JENKINS/Token+Macro+Plugin symRootValue = TokenMacro.expandAll(build, projectRoot, listener, symRoot).trim(); } catch (MacroEvaluationException e) { listener.error(Messages.XCodeBuilder_symRootMacroError(e.getMessage())); return false; } } ByteArrayOutputStream output = new ByteArrayOutputStream(); // Try to read CFBundleShortVersionString from project listener.getLogger().println(Messages.XCodeBuilder_fetchingCFBundleShortVersionString()); String cfBundleShortVersionString = ""; int returnCode = launcher.launch().envs(envs).cmds(getGlobalConfiguration().getAgvtoolPath(), "mvers", "-terse1").stdout(output).pwd(projectRoot).join(); // only use this version number if we found it if (returnCode == 0) cfBundleShortVersionString = output.toString().trim(); if (StringUtils.isEmpty(cfBundleShortVersionString)) listener.getLogger().println(Messages.XCodeBuilder_CFBundleShortVersionStringNotFound()); else listener.getLogger().println(Messages.XCodeBuilder_CFBundleShortVersionStringFound(cfBundleShortVersionString)); listener.getLogger().println(Messages.XCodeBuilder_CFBundleShortVersionStringValue(cfBundleShortVersionString)); output.reset(); // Try to read CFBundleVersion from project listener.getLogger().println(Messages.XCodeBuilder_fetchingCFBundleVersion()); String cfBundleVersion = ""; returnCode = launcher.launch().envs(envs).cmds(getGlobalConfiguration().getAgvtoolPath(), "vers", "-terse").stdout(output).pwd(projectRoot).join(); // only use this version number if we found it if (returnCode == 0) cfBundleVersion = output.toString().trim(); if (StringUtils.isEmpty(cfBundleVersion)) listener.getLogger().println(Messages.XCodeBuilder_CFBundleVersionNotFound()); else listener.getLogger().println(Messages.XCodeBuilder_CFBundleVersionFound(cfBundleVersion)); listener.getLogger().println(Messages.XCodeBuilder_CFBundleVersionValue(cfBundleVersion)); String buildDescription = cfBundleShortVersionString + " (" + cfBundleVersion + ")"; XCodeAction a = new XCodeAction(buildDescription); build.addAction(a); // Update the bundle ID if ( BooleanUtils.isTrue(this.changeBundleID) ) { listener.getLogger().println(Messages.XCodeBuilder_CFBundleIdentifierChanged(bundleIDInfoPlistPath, bundleID)); returnCode = launcher.launch().envs(envs).cmds("/usr/libexec/PlistBuddy", "-c", "Set :CFBundleIdentifier " + bundleID, bundleIDInfoPlistPath).stdout(listener).pwd(projectRoot).join(); if (returnCode > 0) { listener.fatalError(Messages.XCodeBuilder_CFBundleIdentifierInfoPlistNotFound(bundleIDInfoPlistPath)); return false; } } // Update the Marketing version (CFBundleShortVersionString) if ( BooleanUtils.isTrue(this.provideApplicationVersion) && !StringUtils.isEmpty(cfBundleShortVersionStringValue)) { try { // If not empty we use the Token Expansion to replace it // https://wiki.jenkins-ci.org/display/JENKINS/Token+Macro+Plugin cfBundleShortVersionString = TokenMacro.expandAll(build, projectRoot, listener, cfBundleShortVersionStringValue); listener.getLogger().println(Messages.XCodeBuilder_CFBundleShortVersionStringUpdate(cfBundleShortVersionString)); returnCode = launcher.launch().envs(envs).cmds(getGlobalConfiguration().getAgvtoolPath(), "new-marketing-version", cfBundleShortVersionString).stdout(listener).pwd(projectRoot).join(); if (returnCode > 0) { listener.fatalError(Messages.XCodeBuilder_CFBundleShortVersionStringUpdateError(cfBundleShortVersionString)); return false; } } catch (MacroEvaluationException e) { listener.fatalError(Messages.XCodeBuilder_CFBundleShortVersionStringMacroError(e.getMessage())); // Fails the build return false; } } // Update the Technical version (CFBundleVersion) if ( BooleanUtils.isTrue(this.provideApplicationVersion) && !StringUtils.isEmpty(cfBundleVersionValue)) { try { // If not empty we use the Token Expansion to replace it // https://wiki.jenkins-ci.org/display/JENKINS/Token+Macro+Plugin cfBundleVersion = TokenMacro.expandAll(build, projectRoot, listener, cfBundleVersionValue); listener.getLogger().println(Messages.XCodeBuilder_CFBundleVersionUpdate(cfBundleVersion)); returnCode = launcher.launch().envs(envs).cmds(getGlobalConfiguration().getAgvtoolPath(), "new-version", "-all", cfBundleVersion).stdout(listener).pwd(projectRoot).join(); if (returnCode > 0) { listener.fatalError(Messages.XCodeBuilder_CFBundleVersionUpdateError(cfBundleVersion)); return false; } } catch (MacroEvaluationException e) { listener.fatalError(Messages.XCodeBuilder_CFBundleVersionMacroError(e.getMessage())); // Fails the build return false; } } listener.getLogger().println(Messages.XCodeBuilder_CFBundleShortVersionStringUsed(cfBundleShortVersionString)); listener.getLogger().println(Messages.XCodeBuilder_CFBundleVersionUsed(cfBundleVersion)); String developmentTeamID = null; boolean archiveAutomaticSigning = false; if ( signingMethod != null && signingMethod.equals("readFromProject") ) { provisioningProfiles = new ArrayList<>(); listener.getLogger().println(Messages.XCodeBuilder_ReadSigningInfoFromProject()); XcodeProject xcodeProject = null; ArrayList projectLocations = new ArrayList(); // Retrieve target from Xcode project. FilePath projectLocation = null; if ( !StringUtils.isEmpty(xcodeProjectFile) ) { // Retrieve provisioning profile information from Xcode project file. projectLocation = projectRoot.child(xcodeProjectFile); if ( !projectLocation.exists() || !projectLocation.isDirectory() ) { listener.getLogger().println(Messages.XCodeBuilder_CouldNotReadInfoFrom(projectLocation.absolutize().getRemote())); projectLocation = null; } } // JENKINS-54113 if ( !StringUtils.isEmpty(xcodeWorkspaceFile) ) { // Retrieve target from Xcode workspace. listener.getLogger().println(Messages.XCodeBuilder_ReadInfoFromWorkspace(xcodeWorkspaceFile)); List projectList = XcodeProjectParser.parseXcodeWorkspace(projectRoot.child(xcodeWorkspaceFile + ".xcworkspace")); if ( projectList == null ) { listener.getLogger().println("Empty or Invalid workspacefile: " + projectRoot.child(xcodeWorkspaceFile + ".xcworkspace").absolutize().getRemote()); } else if ( projectList.size() > 0 && xcodeSchema != null && !StringUtils.isEmpty(xcodeSchema) ) { for ( String location : projectList ) { HashMap xcodeSchemes = XcodeProjectParser.listXcodeSchemes(projectRoot.child(location)); // JENKINS-59523, JENKINS-59609 if ( xcodeSchemes == null ) { listener.getLogger().println("Skipping empty or invalid scheme file: " + location); continue; } ProjectScheme projectScheme = xcodeSchemes.get(xcodeSchema); // JENKINS-59523, JENKINS-59609 if ( projectScheme == null ) { listener.getLogger().println("Skipping undefined schema: " + xcodeSchema); continue; } String referencedContainerLocation = projectScheme.referencedContainer.replaceAll("^container:", ""); projectLocation = projectRoot.child(referencedContainerLocation); target = projectScheme.blueprintName; break; } } else if ( projectList.size() > 1 ) { // Xcode build generates an error if there are multiple xcodeproj. listener.fatalError(Messages.XCodeBuilder_MultipleProjectInWorkSpace()); return false; } else { // Workspace file have only one project. projectLocation = projectRoot.child(projectList.get(0)); } } if ( projectLocation == null ) { // Retrieve xcodeproj from current working directory. List xcodeProjects = projectRoot.list(new XcodeProjectFileFilter()); if ( xcodeProjects == null ) { listener.fatalError(Messages.XCodeBuilder_NoArchivesInBuildDirectory(projectRoot.absolutize().getRemote())); return false; } if ( xcodeProjects.size() > 1 ) { // Xcode build generates an error if there are multiple xcodeproj. listener.fatalError(Messages.XCodeBuilder_MultipleProjectInWorkSpace()); return false; } projectLocation = xcodeProjects.get(0); } projectLocations.add(projectLocation); for ( FilePath examineLocation : projectLocations ) { // Parse Xcode project file. xcodeProject = XcodeProjectParser.parseXcodeProject(examineLocation); if ( xcodeProject == null ) { listener.getLogger().println(Messages.XCodeBuilder_CouldNotReadProjectInfoFrom(examineLocation.absolutize().getRemote())); return false; } // Examine all targets. for ( String key : xcodeProject.projectTarget.keySet() ) { ProjectTarget projectTarget = xcodeProject.projectTarget.get(key); String exportConfiguration = null; if ( !StringUtils.isEmpty(ipaExportMethod) ) { if ( ipaExportMethod.equals("app-store") ) { exportConfiguration = "Release"; } else if ( ipaExportMethod.equals("enterprise") ) { exportConfiguration = "Enterprise"; } else if ( ipaExportMethod.equals("ad-hoc") ) { exportConfiguration = "AdHoc"; } else { exportConfiguration = "Debug"; } } else if ( StringUtils.isEmpty(configuration) ) { exportConfiguration = projectTarget.defaultConfigurationName; } boolean automaticSigning = projectTarget.provisioningStyle.equals("Automatic"); if ( projectTarget.testTargetID == null ) { // The target is not a test. archiveAutomaticSigning = automaticSigning; } BuildConfiguration buildConfiguration = projectTarget.buildConfiguration.get(exportConfiguration); if ( buildConfiguration == null ) { listener.getLogger().println(Messages.XCodeBuilder_CouldNotGetBuildConfig(exportConfiguration, examineLocation.absolutize().getRemote())); exportConfiguration = "Release"; buildConfiguration = projectTarget.buildConfiguration.get(exportConfiguration); if ( buildConfiguration == null ) { return false; } else { // Fallback to Release configuretion.` listener.getLogger().println(Messages.XCodeBuilder_UseingReleaseConfigFor()); } } if ( buildConfiguration.developmentTeamId != null ) { developmentTeamID = buildConfiguration.developmentTeamId; listener.getLogger().println(Messages.XCodeBuilder_FoundDevelopmentTeamID(developmentTeamID, examineLocation.absolutize().getRemote())); } if ( !automaticSigning ) { String provisioningProfileUUID = buildConfiguration.provisioningProfileUUID; String provisioningProfileSpecifier = buildConfiguration.provisioningProfileSpecifier; String bundleIdentifier = null; if ( buildConfiguration.bundleIdentifier != null ) { bundleIdentifier = buildConfiguration.bundleIdentifier; } else { // Placeholder replacement. // Currentry only support "${TARGET_NAME}" and "$(TARGET_NAME)" String productName = buildConfiguration.productName; productName = productName.replaceAll(Pattern.quote("${TARGET_NAME}"), key); productName = productName.replaceAll(Pattern.quote("$(TARGET_NAME)"), key); InfoPlist infoPlist = XcodeProjectParser.parseInfoPlist(projectRoot.child(buildConfiguration.infoPlistFile)); if ( infoPlist == null ) { listener.getLogger().println(Messages.XCodeBuilder_CouldNotReadInfoFrom(projectRoot.child(buildConfiguration.infoPlistFile).absolutize().getRemote())); return false; } // Placeholder replacement. // Currentry only support "$(PRODUCT_NAME:rfc1034identifier)" bundleIdentifier = infoPlist.getCfBundleIdentifier(); productName = productName.replaceAll(" ", "-"); bundleIdentifier = bundleIdentifier.replaceAll(Pattern.quote("$(PRODUCT_NAME:rfc1034identifier)"), productName); } // PROVISIONING_PROFILE(UUID) or PROVISIONING_PROFILE_SPECIFIER String provisioningProfileIdentifier = null; if ( provisioningProfileSpecifier != null ) { // We will use SPECIFIE instead UUID. provisioningProfileIdentifier = provisioningProfileSpecifier; } else { provisioningProfileIdentifier = provisioningProfileUUID; } if ( provisioningProfileIdentifier != null ) { provisioningProfiles.add(new ProvisioningProfile(bundleIdentifier, provisioningProfileIdentifier)); } } if ( StringUtils.isEmpty(configuration) && projectTarget.productType.equals("com.apple.product-type.application") ) { configuration = exportConfiguration; } } } for ( ProvisioningProfile rp : provisioningProfiles ) { listener.getLogger().println("UUID/SPECIFIER CFbundleIdentifier"); listener.getLogger().println(rp.getProvisioningProfileUUID() + " " + rp.getProvisioningProfileAppId()); } } else { // If developmentTeamName is set the developmentTeamID is invalid. if ( StringUtils.isEmpty(developmentTeamName) ) { developmentTeamID = envs.expand(this.developmentTeamID); } if (StringUtils.isEmpty(developmentTeamID)) { Team team = getDevelopmentTeam(); if (team == null) { listener.getLogger().println(Messages.XCodeBuilder_teamNotConfigured()); } else { developmentTeamID = envs.expand(team.getTeamID()); if (!StringUtils.isEmpty(developmentTeamID)) { listener.getLogger().println(Messages.XCodeBuilder_DebugInfoCanFindCertificates()); /*returnCode =*/ launcher.launch().envs(envs).cmds("/usr/bin/security", "find-certificate", "-a", "-c", developmentTeamID, "-Z", "|", "grep", "^SHA-1").stdout(listener).pwd(projectRoot).join(); // We could fail here, but this doesn't seem to work as it should right now (output not properly redirected. We might need a parser) } } } } listener.getLogger().println(Messages.XCodeBuilder_DebugInfoAvailableSDKs()); /*returnCode =*/ launcher.launch().envs(envs).cmds(getGlobalConfiguration().getXcodebuildPath(), "-showsdks").stdout(listener).pwd(projectRoot).join(); XcodeBuildListParser xcodebuildListParser; { List commandLine = Lists.newArrayList(getGlobalConfiguration().getXcodebuildPath()); commandLine.add("-list"); // xcodebuild -list -workspace $workspace listener.getLogger().println(Messages.XCodeBuilder_DebugInfoAvailableSchemes()); if (!StringUtils.isEmpty(xcodeWorkspaceFile)) { commandLine.add("-workspace"); commandLine.add(xcodeWorkspaceFile + ".xcworkspace"); } else if (!StringUtils.isEmpty(xcodeProjectFile)) { commandLine.add("-project"); commandLine.add(xcodeProjectFile); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); returnCode = launcher.launch().envs(envs).cmds(commandLine).stdout(baos).pwd(projectRoot).start().joinWithTimeout(10, TimeUnit.SECONDS, listener); String xcodeBuildListOutput = baos.toString("UTF-8"); listener.getLogger().println(xcodeBuildListOutput); boolean timedOut = returnCode == SIGTERM; if (returnCode > 0 && !timedOut) return false; xcodebuildListParser = new XcodeBuildListParser(xcodeBuildListOutput); } XcodeBuildHelpParser xcodebuildHelpParser; { List commandLine = Lists.newArrayList(getGlobalConfiguration().getXcodebuildPath()); commandLine.add("-help"); // xcodebuild -help listener.getLogger().println(Messages.XCodeBuilder_DebugInfoAvailableParameters()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); returnCode = launcher.launch().envs(envs).cmds(commandLine).stdout(baos).pwd(projectRoot).start().joinWithTimeout(10, TimeUnit.SECONDS, listener); String xcodeBuildHelpOutput = baos.toString("UTF-8"); boolean timedOut = returnCode == SIGTERM; if (returnCode > 0 && !timedOut) return false; xcodebuildHelpParser = new XcodeBuildHelpParser(xcodeBuildHelpOutput); } boolean haveAllowProvisioningUpdates = false; List availableParameters = xcodebuildHelpParser.getParameters(); if (availableParameters.isEmpty()) { listener.getLogger().println(Messages.XCodeBuilder_NoAvailableParameters()); haveAllowProvisioningUpdates = false; } else { listener.getLogger().println(StringUtils.join(availableParameters, "\n")); if(availableParameters.contains("-allowProvisioningUpdates")){ haveAllowProvisioningUpdates = true; } } listener.getLogger().println(Messages.XCodeBuilder_DebugInfoLineDelimiter()); String buildDirValue = null; FilePath buildDirectory; if (!StringUtils.isEmpty(buildDir)) { try { buildDirValue = TokenMacro.expandAll(build, projectRoot, listener, buildDir).trim(); } catch (MacroEvaluationException e) { listener.error(Messages.XCodeBuilder_buildDirMacroError(e.getMessage())); return false; } } if (buildDirValue != null) { // If there is a BUILD_DIR, that overrides any use of SYMROOT. Does not require the build platform and the configuration. buildDirectory = new FilePath(projectRoot.getChannel(), buildDirValue); } else if (symRootValue != null) { // If there is a SYMROOT specified, compute the build directory from that. buildDirectory = new FilePath(projectRoot.getChannel(), symRootValue).child(configuration + "-" + buildPlatform); } else { // Assume its a build for the handset, not the simulator. buildDirectory = projectRoot.child("build").child(configuration + "-" + buildPlatform); } listener.getLogger().println(Messages.XCodeBuilder_BuildDirectory(buildDirectory.absolutize())); // XCode Version returnCode = launcher.launch().envs(envs).cmds(getGlobalConfiguration().getXcodebuildPath(), "-version").stdout(listener).pwd(projectRoot).join(); if (returnCode > 0) { listener.fatalError(Messages.XCodeBuilder_xcodeVersionNotFound()); return false; // We fail the build if XCode isn't deployed } // Clean build directories if ( BooleanUtils.isNotFalse(cleanBeforeBuild) ) { listener.getLogger().println(Messages.XCodeBuilder_cleaningBuildDir(buildDirectory.absolutize().getRemote())); buildDirectory.deleteRecursive(); } // remove test-reports and *.ipa if ( BooleanUtils.isTrue(cleanTestReports) ) { listener.getLogger().println(Messages.XCodeBuilder_cleaningTestReportsDir(projectRoot.child("test-reports").absolutize().getRemote())); projectRoot.child("test-reports").deleteRecursive(); } if ( BooleanUtils.isNotFalse(cleanResultBundlePath) && StringUtils.isNotEmpty(resultBundlePath) ) { listener.getLogger().println(Messages.XCodeBuilder_CleaningResultBundlePath(projectRoot.child(resultBundlePath).absolutize().getRemote())); projectRoot.child(resultBundlePath).deleteRecursive(); } if ( BooleanUtils.isTrue(unlockKeychain) ) { // Let's unlock the keychain String keychainPath; String keychainPwd; // for backward compatibility if (StringUtils.isNotEmpty(keychainName)) { listener.getLogger().println(Messages.XCodeBuilder_UseDeprecatedKeychainInfo()); Keychain keychain = getKeychain(keychainName); if (keychain == null) { listener.fatalError(Messages.XCodeBuilder_keychainNotConfigured()); return false; } keychainPath = envs.expand(keychain.getKeychainPath()); keychainPwd = envs.expand(Secret.toString(keychain.getKeychainPassword())); } else if (StringUtils.isNotEmpty(keychainId)) { KeychainPasswordAndPath keychain = getKeychainPasswordAndPath(build.getParent(), keychainId); if (keychain == null) { listener.fatalError(Messages.XCodeBuilder_keychainNotConfigured()); return false; } keychainPath = envs.expand(keychain.getKeychainPath()); keychainPwd = envs.expand(keychain.getPassword().getPlainText()); } else { keychainPath = this.keychainPath; keychainPwd = Secret.toString(this.keychainPwd); } launcher.launch().envs(envs).cmds("/usr/bin/security", "list-keychains", "-s", keychainPath).stdout(listener).pwd(projectRoot).join(); launcher.launch().envs(envs).cmds("/usr/bin/security", "default-keychain", "-d", "user", "-s", keychainPath).stdout(listener).pwd(projectRoot).join(); if (StringUtils.isEmpty(keychainPwd)) returnCode = launcher.launch().envs(envs).cmds("/usr/bin/security", "unlock-keychain", keychainPath).stdout(listener).pwd(projectRoot).join(); else returnCode = launcher.launch().envs(envs).cmds("/usr/bin/security", "unlock-keychain", "-p", keychainPwd, keychainPath).masks(false, false, false, true, false).stdout(listener).pwd(projectRoot).join(); if (returnCode > 0) { listener.fatalError(Messages.XCodeBuilder_unlockKeychainFailed()); return false; } // Show the keychain info after unlocking, if not, OS X will prompt for the keychain password launcher.launch().envs(envs).cmds("/usr/bin/security", "show-keychain-info", keychainPath).stdout(listener).pwd(projectRoot).join(); } // display useful setup information listener.getLogger().println(Messages.XCodeBuilder_DebugInfoLineDelimiter()); listener.getLogger().println(Messages.XCodeBuilder_DebugInfoAvailableCertificates()); /*returnCode =*/ launcher.launch().envs(envs).cmds("/usr/bin/security", "find-identity", "-p", "codesigning", "-v").stdout(listener).pwd(projectRoot).join(); // Build if ( BooleanUtils.isNotTrue(skipBuildStep) ) { StringBuilder xcodeReport = new StringBuilder(Messages.XCodeBuilder_invokeXcodebuild()); JenkinsXCodeBuildOutputParser reportGenerator = new JenkinsXCodeBuildOutputParser(projectRoot, listener); List commandLine = Lists.newArrayList(getGlobalConfiguration().getXcodebuildPath()); // Workspace and target can not be specified at the same time. // also specify workspace you must specify a scheme. if ( !StringUtils.isEmpty(xcodeWorkspaceFile) ) { if ( StringUtils.isEmpty(xcodeSchema) ) { listener.getLogger().println(Messages.XCodeBuilder_SpecifyWorkspaceAlsoSetScheme()); return false; } } // Prioritizing schema over target setting if (!StringUtils.isEmpty(xcodeSchema)) { commandLine.add("-scheme"); commandLine.add(xcodeSchema); xcodeReport.append(", scheme: ").append(xcodeSchema); } else if (StringUtils.isEmpty(target)) { // When target is empty always build all targets. commandLine.add("-alltargets"); xcodeReport.append("target: ALL"); } else if( BooleanUtils.isTrue(interpretTargetAsRegEx) ) { if(xcodebuildListParser.getTargets().isEmpty()) { listener.getLogger().println(Messages.XCodeBuilder_NoTargetsFoundInConfig()); return false; } Collection matchedTargets = Collections2.filter(xcodebuildListParser.getTargets(), Predicates.containsPattern(target)); if (matchedTargets.isEmpty()) { listener.getLogger().println(Messages.XCodeBuilder_NoMatchingTargetsFound()); return false; } for (String matchedTarget : matchedTargets) { commandLine.add("-target"); commandLine.add(matchedTarget); xcodeReport.append("target: ").append(matchedTarget); } } else { commandLine.add("-target"); commandLine.add(target); xcodeReport.append("target: ").append(target); } if (!StringUtils.isEmpty(sdk)) { commandLine.add("-sdk"); commandLine.add(sdk); xcodeReport.append(", sdk: ").append(sdk); } else { xcodeReport.append(", sdk: DEFAULT"); } // Prioritizing workspace over project setting if (!StringUtils.isEmpty(xcodeWorkspaceFile)) { commandLine.add("-workspace"); commandLine.add(xcodeWorkspaceFile + ".xcworkspace"); xcodeReport.append(", workspace: ").append(xcodeWorkspaceFile); } else if (!StringUtils.isEmpty(xcodeProjectFile)) { commandLine.add("-project"); commandLine.add(xcodeProjectFile); xcodeReport.append(", project: ").append(xcodeProjectFile); } else { xcodeReport.append(", project: DEFAULT"); } if (!StringUtils.isEmpty(configuration)) { commandLine.add("-configuration"); commandLine.add(configuration); xcodeReport.append(", configuration: ").append(configuration); } if ( BooleanUtils.isNotFalse(cleanBeforeBuild) ) { commandLine.add("clean"); xcodeReport.append(", clean: YES"); } else { xcodeReport.append(", clean: NO"); } //Bug JENKINS-30362 //Generating an archive builds the project twice //commandLine.add("build"); FilePath archiveLocation = buildDirectory.absolutize().child(xcodeSchema + ".xcarchive"); if ( BooleanUtils.isTrue(buildIpa) || BooleanUtils.isTrue(generateArchive) ) { commandLine.add("archive"); commandLine.add("-archivePath"); commandLine.add(archiveLocation.getRemote()); xcodeReport.append(", archive:YES"); }else{ xcodeReport.append(", archive:NO"); commandLine.add("build"); } //END Bug JENKINS-30362 if ( BooleanUtils.isTrue(noConsoleLog) ) { xcodeReport.append(", consolelog:NO"); reportGenerator.setConsoleLog(false); }else{ xcodeReport.append(", consolelog:YES"); } if(!StringUtils.isEmpty(logfileOutputDirectory)) { xcodeReport.append(", logfileOutputDirectory: ").append(logfileOutputDirectory); reportGenerator.setLogfilePath(buildDirectory, logfileOutputDirectory); } if ( !StringUtils.isEmpty(resultBundlePath) || BooleanUtils.isTrue(ignoreTestResults) ) { reportGenerator.setIgnoreTestResults(true); } if ( !StringUtils.isEmpty(resultBundlePath) ) { commandLine.add("-resultBundlePath"); commandLine.add(resultBundlePath); xcodeReport.append(", resultBundlePath: ").append(resultBundlePath); } if (!StringUtils.isEmpty(symRootValue)) { commandLine.add("SYMROOT=" + symRootValue); xcodeReport.append(", symRoot: ").append(symRootValue); } else { xcodeReport.append(", symRoot: DEFAULT"); } // BUILD_DIR if (!StringUtils.isEmpty(buildDirValue)) { commandLine.add("BUILD_DIR=" + buildDirValue); xcodeReport.append(", buildDir: ").append(buildDirValue); } else { xcodeReport.append(", buildDir: DEFAULT"); } // handle code signing identities if (!StringUtils.isEmpty(developmentTeamID)) { commandLine.add("DEVELOPMENT_TEAM=" + developmentTeamID); xcodeReport.append(", developmentTeamID: ").append(developmentTeamID); } else { xcodeReport.append(", developmentTeamID: AUTOMATIC"); } // Allow updating signing assets if ( haveAllowProvisioningUpdates && ( archiveAutomaticSigning || signingMethod == null || signingMethod.equals("automatic") ) ) { commandLine.add("-allowProvisioningUpdates"); xcodeReport.append(", allowProvisioningUpdates: YES"); } // Additional (custom) xcodebuild arguments if (!StringUtils.isEmpty(xcodebuildArguments)) { commandLine.addAll(splitXcodeBuildArguments(xcodebuildArguments)); } boolean manualSigning = (!archiveAutomaticSigning && signingMethod != null && (signingMethod.equals("manual") || signingMethod.equals("readFromProject"))); if ( manualSigning ) { if ( provisioningProfiles != null && provisioningProfiles.size() > 0 ) { for ( ProvisioningProfile pp : provisioningProfiles ) { String provisioningProfileUUID = envs.expand(pp.getProvisioningProfileUUID()); if ( !StringUtils.isEmpty(provisioningProfileUUID) && provisioningProfileUUID.endsWith(".mobileprovision") ) { // If provisioningProfileUUID is an .mobileprovision file, // obtain the profile UUID from .mobileprovision and use it. String provisioningProfileName = provisioningProfileUUID; try { output.reset(); returnCode = launcher.launch().envs(envs).cmds("/bin/sh", "-c", "/usr/libexec/PlistBuddy -c \"Print :UUID\" /dev/stdin <<< $(/usr/bin/security cms -D -i \"" + projectRoot.absolutize().child(provisioningProfileUUID).getRemote() + "\")").stdout(output).stderr(System.err).pwd(projectRoot).join(); if ( returnCode == 0 ) { FilePath homePath = projectRoot.getHomeDirectory(projectRoot.getChannel()); FilePath provisioningProfilePath = projectRoot.child(provisioningProfileUUID); provisioningProfileUUID = output.toString().trim(); listener.getLogger().println(Messages.XCodeBuilder_ProfileUUIDReplaceWith(provisioningProfileUUID)); if ( BooleanUtils.isNotFalse(copyProvisioningProfile) ) { // When the provisioning profile is specified in "Provisioning profile UUID", // copy the specified file to "/Users/${HOME}/Library/MobileDevice/Provisioning Profiles/" FilePath profilesLibPath = homePath.child("Library/MobileDevice/Provisioning Profiles"); profilesLibPath.mkdirs(); try { provisioningProfilePath.copyTo(profilesLibPath.child(provisioningProfileUUID + ".mobileprovision")); listener.getLogger().println(Messages.XCodeBuilder_CopiedProvisioningProfile(provisioningProfilePath.getRemote(), profilesLibPath.child(provisioningProfileUUID + ".mobileprovision").getRemote())); } catch ( Exception ex ) { listener.getLogger().println(Messages.XCodeBuilder_FailedToCopyMobileProvision(ex.toString())); return false; } } } else { listener.getLogger().println(Messages.XCodeBuilder_CouldNotGetInfoFromMobileProvision(projectRoot.absolutize().child(provisioningProfileUUID).getRemote())); return false; } } catch(Exception ex) { listener.getLogger().println(Messages.XCodeBuilder_CFBundleIdFailedGetInMobileProvision(projectRoot.absolutize().child(provisioningProfileName).getRemote(), ex.toString())); return false; } } } } } if ( BooleanUtils.isTrue(useLegacyBuildSystem) ) { commandLine.add("-UseModernBuildSystem=NO"); xcodeReport.append(", useLegacyBuildSystem: YES"); } listener.getLogger().println(xcodeReport.toString()); returnCode = launcher.launch().envs(envs).cmds(commandLine).stdout(reportGenerator.getOutputStream()).pwd(projectRoot).join(); reportGenerator.closeLogfile(); if ( !StringUtils.isEmpty(resultBundlePath) ) { XcodeTestSummariesParser testSummariesParser = new XcodeTestSummariesParser(projectRoot); FilePath testSummariesPath = projectRoot.child(resultBundlePath + "/TestSummaries.plist"); if ( testSummariesPath.exists() ) { listener.getLogger().println(Messages.XCodeBuilder_ParseingTestSummariesPlist(testSummariesPath.absolutize().getRemote())); testSummariesParser.parseTestSummariesPlist(testSummariesPath); } else { listener.getLogger().println(Messages.XCodeBuilder_TestSummariesPlistNotExists(testSummariesPath.absolutize().getRemote())); } } if ( BooleanUtils.isNotTrue(allowFailingBuildResults) ) { if (reportGenerator.getExitCode() != 0) return false; if (returnCode > 0) return false; } } // Package IPA if ( BooleanUtils.isTrue(buildIpa) ) { if (!buildDirectory.exists() || !buildDirectory.isDirectory()) { listener.fatalError(Messages.XCodeBuilder_NotExistingBuildDirectory(buildDirectory.absolutize().getRemote())); return false; } // Incase Pipeline build. // Pipeline Editor's error checking is poor and has not checked anything. if ( !ArrayUtils.contains(VALID_IPA_EXPORT_METHODS, ipaExportMethod) ) { String validMethodsMsg = StringUtils.join(VALID_IPA_EXPORT_METHODS, ", "); listener.fatalError(Messages.XCodeBuilder_IpaExportMethodMuestBeOneOfTheFollowing(validMethodsMsg)); return false; } // clean IPA FilePath ipaOutputPath = null; if (ipaOutputDirectory != null && ! StringUtils.isEmpty(ipaOutputDirectory)) { ipaOutputPath = buildDirectory.child(ipaOutputDirectory); // Create if non-existent if (! ipaOutputPath.exists()) { ipaOutputPath.mkdirs(); } } if (ipaOutputPath == null) { ipaOutputPath = buildDirectory; } listener.getLogger().println(Messages.XCodeBuilder_cleaningIPA()); for (FilePath path : ipaOutputPath.list("*.ipa")) { path.delete(); } listener.getLogger().println(Messages.XCodeBuilder_cleaningDSYM()); for (FilePath path : ipaOutputPath.list("*-dSYM.zip")) { path.delete(); } // packaging IPA listener.getLogger().println(Messages.XCodeBuilder_packagingIPA()); // Writeing exportOptions.plist boolean manualSigning = (!archiveAutomaticSigning && signingMethod != null && (signingMethod.equals("manual") || signingMethod.equals("readFromProject"))); NSDictionary exportOptionsPlist = new NSDictionary(); exportOptionsPlist.put("signingStyle", manualSigning ? "manual" : "automatic"); exportOptionsPlist.put("method", ipaExportMethod); if ( !StringUtils.isEmpty(developmentTeamID) ) { exportOptionsPlist.put("teamID", developmentTeamID); } if ( manualSigning ) { exportOptionsPlist.put("signingCertificate", ipaExportMethod.equals("development") ? DEV_SIGNING_CERTIFICATE_SELECTOR : DIST_SIGNING_CERTIFICATE_SELECTOR); if ( provisioningProfiles != null && provisioningProfiles.size() > 0 ) { NSDictionary provisioningProfileDict = new NSDictionary(); for ( ProvisioningProfile pp : provisioningProfiles ) { String provisioningProfileAppId = envs.expand(pp.getProvisioningProfileAppId()); if ( !StringUtils.isEmpty(provisioningProfileAppId) && provisioningProfileAppId.endsWith(".plist") ) { // If provisioningProfileAppId is an Info.plist file, // obtain the Bundle ID from Info.plist and use it. try { output.reset(); returnCode = launcher.launch().envs(envs).cmds("/usr/libexec/PlistBuddy", "-c", "Print :CFBundleIdentifier", projectRoot.absolutize().child(provisioningProfileAppId).getRemote()).stdout(output).pwd(projectRoot).join(); if (returnCode == 0) { provisioningProfileAppId = output.toString().trim(); listener.getLogger().println(Messages.XCodeBuilder_CFBundleIdReplaceWith(provisioningProfileAppId)); } else { // When Info.plist generated by Xcodebuild is specified. output.reset(); returnCode = launcher.launch().envs(envs).cmds("/usr/libexec/PlistBuddy", "-c", "Print :ApplicationProperties:CFBundleIdentifier", projectRoot.absolutize().child(provisioningProfileAppId).getRemote()).stdout(output).pwd(projectRoot).join(); if (returnCode == 0) { provisioningProfileAppId = output.toString().trim(); listener.getLogger().println(Messages.XCodeBuilder_CFBundleIdReplaceWith(provisioningProfileAppId)); } } } catch(Exception ex) { listener.getLogger().println(Messages.XCodeBuilder_CFBundleIdFailedGetInInfoPlist(projectRoot.absolutize().child(provisioningProfileAppId).getRemote(), ex.toString())); } } String provisioningProfileUUID = envs.expand(pp.getProvisioningProfileUUID()); if ( !StringUtils.isEmpty(provisioningProfileUUID) && provisioningProfileUUID.endsWith(".mobileprovision") ) { // If provisioningProfileUUID is an .mobileprovision file, // obtain the profile UUID from .mobileprovision and use it. String provisioningProfileName = provisioningProfileUUID; try { output.reset(); returnCode = launcher.launch().envs(envs).cmds("/bin/sh", "-c", "/usr/libexec/PlistBuddy -c \"Print :UUID\" /dev/stdin <<< $(/usr/bin/security cms -D -i \"" + projectRoot.absolutize().child(provisioningProfileUUID).getRemote() + "\")").stdout(output).stderr(System.err).pwd(projectRoot).join(); if ( returnCode == 0 ) { FilePath homePath = projectRoot.getHomeDirectory(projectRoot.getChannel()); FilePath provisioningProfilePath = projectRoot.child(provisioningProfileUUID); provisioningProfileUUID = output.toString().trim(); listener.getLogger().println(Messages.XCodeBuilder_ProfileUUIDReplaceWith(provisioningProfileUUID)); if ( BooleanUtils.isNotFalse(copyProvisioningProfile) && BooleanUtils.isTrue(skipBuildStep) ) { // When the provisioning profile is specified in "Provisioning profile UUID", // copy the specified file to "/Users/${HOME}/Library/MobileDevice/Provisioning Profiles/" FilePath profilesLibPath = homePath.child("Library/MobileDevice/Provisioning Profiles"); profilesLibPath.mkdirs(); try { provisioningProfilePath.copyTo(profilesLibPath.child(provisioningProfileUUID + ".mobileprovision")); listener.getLogger().println(Messages.XCodeBuilder_CopiedProvisioningProfile(provisioningProfilePath.getRemote(), profilesLibPath.child(provisioningProfileUUID + ".mobileprovision").getRemote())); } catch ( Exception ex ) { listener.getLogger().println(Messages.XCodeBuilder_FailedToCopyMobileProvision(ex.toString())); return false; } } } else { listener.getLogger().println(Messages.XCodeBuilder_CouldNotGetInfoFromMobileProvision(projectRoot.absolutize().child(provisioningProfileName).getRemote())); return false; } } catch(Exception ex) { listener.getLogger().println(Messages.XCodeBuilder_CFBundleIdFailedGetInMobileProvision(projectRoot.absolutize().child(provisioningProfileAppId).getRemote(), ex.toString())); return false; } } provisioningProfileDict.put(provisioningProfileAppId, provisioningProfileUUID); } exportOptionsPlist.put("provisioningProfiles", provisioningProfileDict); } } exportOptionsPlist.put("iCloudContainerEnvironment", ipaExportMethod.equals("app-store") ? PRODUCTION_ENV : DEVELOPMENT_ENV); exportOptionsPlist.put("stripSwiftSymbols", stripSwiftSymbols); // Extra options if ( ipaExportMethod.equals("app-store") ) { exportOptionsPlist.put("uploadBitcode", uploadBitcode); exportOptionsPlist.put("uploadSymbols", uploadSymbols); } else { if ( !StringUtils.isEmpty(thinning) ) { exportOptionsPlist.put("thinning", thinning); } exportOptionsPlist.put("compileBitcode", compileBitcode); if ( BooleanUtils.isNotFalse(embedOnDemandResourcesAssetPacksInBundle) && !StringUtils.isEmpty(onDemandResourcesAssetPacksBaseURL) ) { exportOptionsPlist.put("embedOnDemandResourcesAssetPacksInBundle", false); exportOptionsPlist.put("onDemandResourcesAssetPacksBaseURL", onDemandResourcesAssetPacksBaseURL); } if ( !StringUtils.isEmpty(appURL) ) { NSDictionary manifestPlistOprions = new NSDictionary(); manifestPlistOprions.put("appURL", appURL); if ( !StringUtils.isEmpty(displayImageURL) ) { manifestPlistOprions.put("displayImageURL", displayImageURL); } if ( !StringUtils.isEmpty(fullSizeImageURL) ) { manifestPlistOprions.put("fullSizeImageURL", fullSizeImageURL); } if ( !StringUtils.isEmpty(assetPackManifestURL) ) { manifestPlistOprions.put("assetPackManifestURL", assetPackManifestURL); } exportOptionsPlist.put("manifest", manifestPlistOprions); } } ByteArrayOutputStream stream = new ByteArrayOutputStream(); PropertyListParser.saveAsXML(exportOptionsPlist, stream); FilePath exportOptionsPlistLocation = ipaOutputPath.child(ipaExportMethod + ((developmentTeamID == null || StringUtils.isEmpty(developmentTeamID)) ? "AUTOMATIC" : developmentTeamID) + "ExportOptions.plist"); exportOptionsPlistLocation.write(stream.toString(), "UTF-8"); List archives = buildDirectory.list(new XCArchiveFileFilter()); // FilePath is based on File.listFiles() which can randomly fail | http://stackoverflow.com/questions/3228147/retrieving-the-underlying-error-when-file-listfiles-return-null if ( archives == null || archives.size() < 1 ) { listener.fatalError(Messages.XCodeBuilder_NoArchivesInBuildDirectory(buildDirectory.absolutize().getRemote())); return false; } for (FilePath archive : archives) { String version = ""; String shortVersion = ""; try { output.reset(); returnCode = launcher.launch().envs(envs).cmds("/usr/libexec/PlistBuddy", "-c", "Print :ApplicationProperties:CFBundleVersion", archive.absolutize().child("Info.plist").getRemote()).stdout(output).pwd(projectRoot).join(); if (returnCode == 0) { version = output.toString().trim(); } output.reset(); returnCode = launcher.launch().envs(envs).cmds("/usr/libexec/PlistBuddy", "-c", "Print :ApplicationProperties:CFBundleShortVersionString", archive.absolutize().child("Info.plist").getRemote()).stdout(output).pwd(projectRoot).join(); if (returnCode == 0) { shortVersion = output.toString().trim(); } } catch(Exception ex) { listener.getLogger().println(Messages.XCodeBuilder_FailedToGetVersionFromInfoPlist(ex.toString())); return false; } if (StringUtils.isEmpty(version) && StringUtils.isEmpty(shortVersion)) { listener.getLogger().println(Messages.XCodeBuilder_MarketingAndTechnicalVersionNotFound()); return false; } String lastModified = new SimpleDateFormat("yyyy.MM.dd").format(new Date(archive.lastModified())); String baseName = archive.getBaseName().replaceAll(" ", "_") + (shortVersion.isEmpty() ? "" : "-" + shortVersion) + (version.isEmpty() ? "" : "-" + version); // If custom .ipa name pattern has been provided, use it and expand version and build date variables if (! StringUtils.isEmpty(ipaName)) { EnvVars customVars = new EnvVars( "BASE_NAME", archive.getBaseName().replaceAll(" ", "_"), "VERSION", version, "SHORT_VERSION", shortVersion, "BUILD_DATE", lastModified ); baseName = customVars.expand(ipaName); } String ipaFileName = baseName + ".ipa"; FilePath ipaLocation = ipaOutputPath.child(ipaFileName); FilePath payload = ipaOutputPath.child("Payload"); payload.deleteRecursive(); payload.mkdirs(); listener.getLogger().println(Messages.XCodeBuilder_PackagingArchiveToIpa(archive.getBaseName(), ipaLocation.absolutize().getRemote())); if (buildPlatform.contains("simulator")) { listener.getLogger().println(Messages.XCodeBuilder_warningPackagingIPAForSimulatorSDK(sdk)); } List packageCommandLine = new ArrayList<>(); packageCommandLine.add(getGlobalConfiguration().getXcodebuildPath()); packageCommandLine.addAll(Lists.newArrayList("-exportArchive", "-archivePath", archive.absolutize().getRemote(), "-exportPath", ipaOutputPath.absolutize().getRemote(), "-exportOptionsPlist", exportOptionsPlistLocation.absolutize().getRemote())); if (archiveAutomaticSigning || signingMethod == null || (!signingMethod.equals("manual") && !signingMethod.equals("readFromProject"))) { if (haveAllowProvisioningUpdates) packageCommandLine.add("-allowProvisioningUpdates"); } returnCode = launcher.launch().envs(envs).stdout(listener).pwd(projectRoot).cmds(packageCommandLine).join(); if (returnCode > 0) { listener.getLogger().println(Messages.XCodeBuilder_FailedToBuildIpa(ipaLocation.absolutize().getRemote())); return false; } //rename exported ipa FilePath exportedIpa = ipaOutputPath.child(archive.getBaseName() + ".ipa"); if (exportedIpa.exists()) { exportedIpa.renameTo(ipaLocation); } // also zip up the symbols, if present listener.getLogger().println(Messages.XCodeBuilder_ArchivingDSYM()); List dSYMs = archive.absolutize().child("dSYMs").list(new DSymFileFilter()); if (dSYMs == null || dSYMs.isEmpty()) { listener.getLogger().println(Messages.XCodeBuilder_NoDSYMFileFound(archive.absolutize().child("dSYMs"))); } // JENKINS-54414 // May be, this is no longer necessary. //dSYMs.addAll(buildDirectory.absolutize().child(configuration + "-" + buildPlatform).list(new DSymFileFilter())); if (dSYMs == null || dSYMs.isEmpty()) { listener.getLogger().println(Messages.XCodeBuilder_NoDSYMFileFound(archive.absolutize().child("dSYMs"))); } else { for (FilePath dSYM : dSYMs) { returnCode = launcher.launch() .envs(envs) .stdout(listener) .pwd(buildDirectory) .cmds("ditto", "-c", "-k", "--keepParent", "-rsrc", dSYM.absolutize().getRemote(), ipaOutputPath.child(baseName + "-dSYM.zip") .absolutize() .getRemote()) .join(); if (returnCode > 0) { listener.getLogger().println(Messages.XCodeBuilder_zipFailed(baseName)); return false; } } } payload.deleteRecursive(); } } return true; } @Deprecated public Keychain getKeychain(String keychainName) { if(!StringUtils.isEmpty(keychainName)) { for (Keychain keychain : getGlobalConfiguration().getKeychains()) { if(keychain.getKeychainName().equals(keychainName)) return keychain; } } return null; } public KeychainPasswordAndPath getKeychainPasswordAndPath(Item context, String keychainId) { if(!StringUtils.isEmpty(keychainId)) { return (KeychainPasswordAndPath) CredentialsMatchers.firstOrNull( CredentialsProvider.lookupCredentials(KeychainPasswordAndPath.class, context, ACL.SYSTEM, Collections.EMPTY_LIST), CredentialsMatchers.withId(keychainId)); } return null; } public Team getDevelopmentTeam() { if(!StringUtils.isEmpty(developmentTeamName)) { for (Team team : getGlobalConfiguration().getTeams()) { if(team.getTeamName().equals(developmentTeamName)) return team; } } if(!StringUtils.isEmpty(developmentTeamID)) { return new Team("", developmentTeamID); } return null; } static List splitXcodeBuildArguments(String xcodebuildArguments) { if (xcodebuildArguments == null || xcodebuildArguments.length() == 0) { return new ArrayList<>(0); } final QuotedStringTokenizer tok = new QuotedStringTokenizer(xcodebuildArguments); final List result = new ArrayList<>(); while(tok.hasMoreTokens()) result.add(tok.nextToken()); return result; } public GlobalConfigurationImpl getGlobalConfiguration() { return getDescriptor().getGlobalConfiguration(); } @Override public DescriptorImpl getDescriptor() { return (DescriptorImpl) super.getDescriptor(); } @Extension @Symbol("xcodeBuild") public static final class DescriptorImpl extends BuildStepDescriptor { GlobalConfigurationImpl globalConfiguration; // backward compatibility @Deprecated private transient String xcodebuildPath; private transient String agvtoolPath; private transient String xcrunPath; private transient CopyOnWriteList keychains; private transient CopyOnWriteList teams; public DescriptorImpl() { load(); } @SuppressFBWarnings("UWF_UNWRITTEN_FIELD") @Inject void setGlobalConfiguration(GlobalConfigurationImpl c) { this.globalConfiguration = c; {// data migration from old format boolean modified = false; if (xcodebuildPath!=null) { c.setXcodebuildPath(xcodebuildPath); modified = true; } if (agvtoolPath!=null) { c.setAgvtoolPath(agvtoolPath); modified = true; } if (xcrunPath!=null) { c.setXcrunPath(xcrunPath); modified = true; } if (keychains!=null) { c.setKeychains(new ArrayList<>(keychains.getView())); modified = true; } if (teams!=null) { c.setTeams(new ArrayList<>(teams.getView())); modified = true; } if (modified) { c.save(); save(); // delete the old values from the disk now that the new values are committed } } } @Override public boolean isApplicable(Class jobType) { return true; } @Override public String getDisplayName() { return Messages.XCodeBuilder_xcode(); } public GlobalConfigurationImpl getGlobalConfiguration() { return globalConfiguration; } public String getUUID() { return "" + UUID.randomUUID().getMostSignificantBits(); } public FormValidation doCheckOnDemandResourcesAssetPacksBaseURL(@QueryParameter String value, @QueryParameter Boolean embedOnDemandResourcesAssetPacksInBundle) { if ( StringUtils.isEmpty(value) && BooleanUtils.isFalse(embedOnDemandResourcesAssetPacksInBundle) ) { return FormValidation.error(Messages.XCodeBuilder_NeedOnDemandResourcesURL()); } return FormValidation.ok(); } public FormValidation doCheckIpaExportMethod(@QueryParameter String value, @QueryParameter Boolean buildIpa) { if ( BooleanUtils.isTrue(buildIpa) ) { if ( !ArrayUtils.contains(VALID_IPA_EXPORT_METHODS, value) ) { String validMethodsMsg = StringUtils.join(VALID_IPA_EXPORT_METHODS, ", "); return FormValidation.error(Messages.XCodeBuilder_IpaExportMethodMuestBeOneOfTheFollowing(validMethodsMsg)); } } return FormValidation.ok(); } public FormValidation doCheckXcodeWorkspaceFile(@QueryParameter String value, @QueryParameter String xcodeSchema, @QueryParameter String target) { if ( !StringUtils.isEmpty(value) ) { if ( !StringUtils.isEmpty(target) ) { return FormValidation.error(Messages.XCodeBuilder_WorkspaceAndTargetCantSpecifySameTime()); } if ( StringUtils.isEmpty(xcodeSchema) ) { return FormValidation.error(Messages.XCodeBuilder_SpecifyWorkspaceAlsoSetScheme()); } } return FormValidation.ok(); } public FormValidation doCheckXcodeSchema(@QueryParameter String value, @QueryParameter Boolean generateArchive, @QueryParameter Boolean buildIpa, @QueryParameter String xcodeWorkspaceFile, @QueryParameter String target) { if ( !StringUtils.isEmpty(value) ) { if ( !StringUtils.isEmpty(target) ) { return FormValidation.error(Messages.XCodeBuilder_SchemeAndTargetCantSpecifySameTime()); } } else { if ( !StringUtils.isEmpty(xcodeWorkspaceFile) ) { return FormValidation.error(Messages.XCodeBuilder_SpecifyWorkspaceAlsoSetScheme()); } if ( BooleanUtils.isTrue(generateArchive) || BooleanUtils.isTrue(buildIpa) ) { return FormValidation.error(Messages.XCodeBuilder_NeedSchema()); } } return FormValidation.ok(); } public FormValidation doCheckTarget(@QueryParameter String value, @QueryParameter String xcodeWorkspaceFile, @QueryParameter String xcodeSchema) { if ( !StringUtils.isEmpty(value) ) { if ( !StringUtils.isEmpty(xcodeWorkspaceFile) ) { return FormValidation.error(Messages.XCodeBuilder_WorkspaceAndTargetCantSpecifySameTime()); } if ( !StringUtils.isEmpty(xcodeSchema) ) { return FormValidation.error(Messages.XCodeBuilder_SchemeAndTargetCantSpecifySameTime()); } } return FormValidation.ok(); } } } ================================================ FILE: src/main/java/au/com/rayh/XcodeBuildHelpParser.java ================================================ package au.com.rayh; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; /** * Created by Kazuhide Takahashi on 5/9/14. */ public class XcodeBuildHelpParser { private List parameters = new ArrayList<>(); public XcodeBuildHelpParser(String xcodebuildHelpOutput) { if(xcodebuildHelpOutput == null) { return; } String [] lines = xcodebuildHelpOutput.split("\n"); for(String line : lines) { if (StringUtils.startsWith(line, " -")) { String[] words = line.split(" ", 6); if ( words.length == 6 ) { parameters.add(words[4]); } } } } public List getParameters() { return this.parameters; } } ================================================ FILE: src/main/java/au/com/rayh/XcodeBuildListParser.java ================================================ package au.com.rayh; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.StringUtils; /** * Created by ud10404 on 5/9/14. */ public class XcodeBuildListParser { private List targets = new ArrayList<>(); private List configurations = new ArrayList<>(); private List schemes = new ArrayList<>(); public XcodeBuildListParser(String xcodebuildListOutput) { if(xcodebuildListOutput == null) { return; } String [] lines = xcodebuildListOutput.split("\n"); List curList = null; for(String line : lines) { line = line.trim(); if (StringUtils.isEmpty(line)) { curList = null; } else if("Targets:".equals(line)) { curList = targets; } else if("Build Configurations:".equals(line)) { curList = configurations; } else if("Schemes:".equals(line)) { curList = schemes; } else if(curList != null) { curList.add(line); } } } public List getTargets() { return this.targets; } public List getConfigurations() { return this.configurations; } public List getSchemes() { return this.schemes; } } ================================================ FILE: src/main/java/au/com/rayh/XcodeCredentialsHelper.java ================================================ package au.com.rayh; import com.cloudbees.plugins.credentials.CredentialsMatchers; import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.common.StandardListBoxModel; import hudson.model.ItemGroup; import hudson.security.ACL; import hudson.util.ListBoxModel; import org.apache.commons.lang.StringUtils; import edu.umd.cs.findbugs.annotations.CheckForNull; import java.util.Collections; /** * @author Kazuhide Takahashi */ public class XcodeCredentialsHelper { private XcodeCredentialsHelper() {} @CheckForNull public static KeychainPasswordAndPath getCredentials(String credentialsId, ItemGroup context) { if (StringUtils.isBlank(credentialsId)) { return null; } return (KeychainPasswordAndPath) CredentialsMatchers.firstOrNull( CredentialsProvider.lookupCredentials(KeychainPasswordAndPath.class, context, ACL.SYSTEM, Collections.EMPTY_LIST), CredentialsMatchers.withId(credentialsId)); } public static ListBoxModel doFillCredentialsIdItems(ItemGroup context) { return new StandardListBoxModel() .withEmptySelection() .withMatching( CredentialsMatchers.always(), CredentialsProvider.lookupCredentials(KeychainPasswordAndPath.class, context, ACL.SYSTEM, Collections.EMPTY_LIST)); } } ================================================ FILE: src/main/java/au/com/rayh/XcodeDeclarativeCredentialsHandler.java ================================================ /* * The MIT License * * Copyright (c) 2018, CloudBees, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh; import com.cloudbees.plugins.credentials.common.StandardCredentials; import hudson.Extension; import org.jenkinsci.plugins.pipeline.modeldefinition.model.CredentialsBindingHandler; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @Extension public class XcodeDeclarativeCredentialsHandler extends CredentialsBindingHandler { @NonNull @Override public Class type() { return KeychainPasswordAndPath.class; } @NonNull @Override public List> getWithCredentialsParameters(String credentialsId) { Map map = new HashMap<>(); map.put("$class", KeychainPasswordAndPathBinding.class.getName()); map.put("password", "password"); map.put("keychainPath", "keychainPath"); map.put("isInSearchPath", "isInSearchPath"); map.put("credentialsId", credentialsId); return Collections.singletonList(map); } } ================================================ FILE: src/main/java/au/com/rayh/XcodeProject.java ================================================ package au.com.rayh; //import org.kohsuke.stapler.DataBoundConstructor; import java.util.HashMap; public class XcodeProject { //public String uuid; //public String name; //public String file; public HashMap projectTarget; XcodeProject() { //uuid = null; //name = null; //file = null; projectTarget = new HashMap(); } } ================================================ FILE: src/main/java/au/com/rayh/XcodeProjectFileFilter.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package au.com.rayh; import java.io.File; import java.io.FileFilter; import java.io.Serializable; /** * @author Kazuhide Takahashi */ public class XcodeProjectFileFilter implements FileFilter, Serializable { public boolean accept(File pathname) { return pathname.isDirectory() && pathname.getName().endsWith(".xcodeproj"); } } ================================================ FILE: src/main/java/au/com/rayh/XcodeProjectParser.java ================================================ package au.com.rayh; import java.io.File; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.HashMap; import java.text.ParseException; import java.io.ByteArrayInputStream; import hudson.FilePath; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; //import javax.xml.parsers.ParserException; import javax.xml.parsers.ParserConfigurationException; import java.lang.InterruptedException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.dd.plist.NSDictionary; import com.dd.plist.NSArray; import com.dd.plist.NSNumber; import com.dd.plist.NSObject; import com.dd.plist.NSString; import com.dd.plist.PropertyListFormatException; import com.dd.plist.PropertyListParser; /** * Analyze the Xcode project file and obtain the information necessary for building the application. (Only combinations of UUID and BundleID used for CodeSign now) * @author Kazuhide Takahashi */ public class XcodeProjectParser { /** * Retrieve all Xcode scheme file from project directory. * @param projectLocation Xcode project file location (directory path) * @return the list of schema files found in the project directory and the result (ProjectScheme) of analysis of the contents as a HashMap. If analysis fails, it is empty */ public static HashMap listXcodeSchemes(FilePath projectLocation) { String currentUser = System.getProperty("user.name") ; HashMap schemeList = new HashMap(); List schemeFilesDirList = new ArrayList(); try { if ( projectLocation.child("xcuserdata/" + currentUser + ".xcuserdatad/xcschemes").exists() ) { schemeFilesDirList.add(projectLocation.child("xcuserdata/" + currentUser + ".xcuserdatad/xcschemes")); } if ( projectLocation.child("xcshareddata/xcschemes").exists() ) { schemeFilesDirList.add(projectLocation.child("xcshareddata/xcschemes")); } } catch ( IOException ex ) { ex.printStackTrace(); schemeList = null; } catch ( InterruptedException ex ) { ex.printStackTrace(); schemeList = null; } for ( FilePath schemeFilesDir : schemeFilesDirList ) { try { List files = schemeFilesDir.list(new XcodeSchemeFileFilter()); for ( FilePath file : files ) { ProjectScheme scheme = parseXcodeScheme(file); String schemeName = file.getBaseName().replaceAll(".xcscheme$", ""); schemeList.put(schemeName, scheme); } } catch ( IOException ex ) { ex.printStackTrace(); schemeList = null; } catch ( InterruptedException ex ) { ex.printStackTrace(); schemeList = null; } } return schemeList; } /** * @param schemeFile Xcode schieme file location * @return analysis result of Xcode projectscheme file. If analysis fails, it is null */ public static ProjectScheme parseXcodeScheme(FilePath schemeFile) { ProjectScheme projectScheme = new ProjectScheme(); try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); String FEATURE = null; FEATURE = "http://apache.org/xml/features/disallow-doctype-decl"; factory.setFeature(FEATURE, true); FEATURE = "http://xml.org/sax/features/external-general-entities"; factory.setFeature(FEATURE, false); FEATURE = "http://xml.org/sax/features/external-parameter-entities"; factory.setFeature(FEATURE, false); FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd"; factory.setFeature(FEATURE, false); factory.setXIncludeAware(false); factory.setExpandEntityReferences(false); DocumentBuilder documentBuilder = factory.newDocumentBuilder(); Document document = documentBuilder.parse(schemeFile.read()); Element root = document.getDocumentElement(); if ( root.getNodeName().equals("Scheme") ) { NodeList schemeNodes = root.getChildNodes(); for ( int i = 0; i < schemeNodes.getLength(); i++ ) { Node node = schemeNodes.item(i); if ( node.getNodeType() == Node.ELEMENT_NODE ) { Element element = (Element)node; if ( element.getNodeName().equals("BuildAction") ) { //projectScheme.parallelizeBuildables = element.getAttribute("parallelizeBuildables"); //projectScheme.buildImplicitDependencies = element.getAttribute("buildImplicitDependencies"); NodeList buildActionNodes = element.getChildNodes(); for ( int j = 0; j < buildActionNodes.getLength(); j++ ) { node = buildActionNodes.item(j); if ( node.getNodeType() == Node.ELEMENT_NODE ) { element = (Element)node; if ( element.getNodeName().equals("BuildActionEntries") ) { NodeList buildActionEntriesNodes = element.getChildNodes(); for ( int k = 0; k < buildActionEntriesNodes.getLength(); k++ ) { node = buildActionEntriesNodes.item(k); if ( node.getNodeType() == Node.ELEMENT_NODE ) { element = (Element)node; if ( element.getNodeName().equals("BuildActionEntry") ) { //projectScheme.buildForTesting = element.getAttribute("buildForTesting"); //projectScheme.buildForRunning = element.getAttribute("buildForRunning"); //projectScheme.buildForProfiling = element.getAttribute("buildForProfiling"); //projectScheme.buildForArchiving = element.getAttribute("buildForArchiving"); //projectScheme.buildForAnalyzing = element.getAttribute("buildForAnalyzing"); NodeList buildActionEntryNodes = element.getChildNodes(); for ( int l = 0; l < buildActionEntryNodes.getLength(); l++ ) { node = buildActionEntryNodes.item(l); if ( node.getNodeType() == Node.ELEMENT_NODE ) { element = (Element)node; if ( element.getNodeName().equals("BuildableReference") ) { //projectScheme.buildableIdentifier = element.getAttribute("BuildableIdentifier"); //projectScheme.blueprintIdentifier = element.getAttribute("BlueprintIdentifier"); //projectScheme.buildableName = element.getAttribute("BuildableName"); projectScheme.blueprintName = element.getAttribute("BlueprintName"); projectScheme.referencedContainer = element.getAttribute("ReferencedContainer"); } } } } } } } } } } } } } } catch (SAXException ex) { ex.printStackTrace(); projectScheme = null; } catch (IOException ex) { ex.printStackTrace(); projectScheme = null; } catch (ParserConfigurationException ex) { ex.printStackTrace(); projectScheme = null; } catch ( InterruptedException ex ) { ex.printStackTrace(); projectScheme = null; } return projectScheme; } /** * @param workspaceFileLocation Xcode workspace file location (directory) * @return list of project files obtained as a result of analyzing workspaceFile. If analysis fails, it is empty */ public static List parseXcodeWorkspace(FilePath workspaceFileLocation) { List projectList = new ArrayList<>(); try { FilePath workspaceFilePath = workspaceFileLocation.child("contents.xcworkspacedata"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); String FEATURE = null; FEATURE = "http://apache.org/xml/features/disallow-doctype-decl"; factory.setFeature(FEATURE, true); FEATURE = "http://xml.org/sax/features/external-general-entities"; factory.setFeature(FEATURE, false); FEATURE = "http://xml.org/sax/features/external-parameter-entities"; factory.setFeature(FEATURE, false); FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd"; factory.setFeature(FEATURE, false); factory.setXIncludeAware(false); factory.setExpandEntityReferences(false); DocumentBuilder documentBuilder = factory.newDocumentBuilder(); Document document = documentBuilder.parse(workspaceFilePath.read()); Element root = document.getDocumentElement(); if ( root.getNodeName().equals("Workspace") ) { NodeList rootChildren = root.getChildNodes(); for ( int i = 0; i < rootChildren.getLength(); i++ ) { Node node = rootChildren.item(i); if ( node.getNodeType() == Node.ELEMENT_NODE ) { Element element = (Element)node; if ( element.getNodeName().equals("FileRef") ) { String projectLocation = element.getAttribute("location"); if ( projectLocation.startsWith("group:") ) { projectLocation = projectLocation.replaceAll("^group:", ""); projectList.add(projectLocation); } } } } } } catch (SAXException ex) { ex.printStackTrace(); projectList = null; } catch (IOException ex) { ex.printStackTrace(); projectList = null; } catch (ParserConfigurationException ex) { ex.printStackTrace(); projectList = null; } catch ( InterruptedException ex ) { ex.printStackTrace(); projectList = null; } return projectList; } /** * @param infoPlistFile Xcode Info.plist file location * @return analysis result of Info.plist file. If analysis fails, it is null */ public static InfoPlist parseInfoPlist(FilePath infoPlistFile) { InfoPlist infoPlist = null; try { NSDictionary rootDict = (NSDictionary)PropertyListParser.parse(infoPlistFile.read()); String cfBundleIdentifier = rootDict.objectForKey("CFBundleIdentifier").toString(); String cfBundleVersion = rootDict.objectForKey("CFBundleVersion").toString(); String cfBundleShortVersionString = rootDict.objectForKey("CFBundleShortVersionString").toString(); infoPlist = new InfoPlist(infoPlistFile, cfBundleIdentifier, cfBundleVersion, cfBundleShortVersionString); } catch ( Exception ex ) { ex.printStackTrace(); } return infoPlist; } /** * @param projectLocation Xcode project file location (directory) * @return analysis result of Xcode project file. If analysis fails, it is null */ public static XcodeProject parseXcodeProject(FilePath projectLocation) { XcodeProject project = new XcodeProject(); FilePath xcodeProjectFile = projectLocation.child("project.pbxproj"); try { NSDictionary rootDict = (NSDictionary)PropertyListParser.parse(xcodeProjectFile.read()); String rootObjectsUUID = rootDict.objectForKey("rootObject").toString(); NSDictionary objectsDict = ((NSDictionary)rootDict.objectForKey("objects")); NSDictionary pbxProjectSectionDict = ((NSDictionary)objectsDict.objectForKey(rootObjectsUUID)); NSObject[] projectTargetUUIDs = ((NSArray)pbxProjectSectionDict.objectForKey("targets")).getArray(); // In case Project has buildConfigurationList. // Parse each targets. for ( NSObject projectTargetUUID:projectTargetUUIDs ) { ProjectTarget target = new ProjectTarget(); NSDictionary projectTargetDict = ((NSDictionary)objectsDict.objectForKey(projectTargetUUID.toString())); target.uuid = projectTargetUUID.toString(); String targetName = projectTargetDict.objectForKey("name").toString(); // Target has buildConfigurationList. String buildConfigurationListUUID = projectTargetDict.objectForKey("buildConfigurationList").toString(); target.productType = projectTargetDict.objectForKey("productType").toString(); if ( target.productType.equals("com.apple.product-type.application") || target.productType.equals("com.apple.product-type.bundle.unit-test") || target.productType.equals("com.apple.product-type.bundle.ui-testing") || target.productType.equals("com.apple.product-type.watchkit-extension") || target.productType.equals("com.apple.product-type.application.watchapp") || target.productType.equals("com.apple.product-type.watchkit2-extension") || target.productType.equals("com.apple.product-type.application.watchapp2") ) { NSDictionary attributesDict = ((NSDictionary)pbxProjectSectionDict.objectForKey("attributes")); NSDictionary targetAttributesDict = ((NSDictionary)attributesDict.objectForKey("TargetAttributes")); NSDictionary attributeDict = ((NSDictionary)targetAttributesDict.objectForKey(target.uuid)); if ( attributeDict.objectForKey("ProvisioningStyle") != null ) { target.provisioningStyle = attributeDict.objectForKey("ProvisioningStyle").toString(); } else { // Default code signing style is "Automatic" target.provisioningStyle = "Automatic"; } if ( attributeDict.objectForKey("TestTargetID") != null ) { target.testTargetID = attributeDict.objectForKey("TestTargetID").toString(); } NSDictionary buildConfigurationList = ((NSDictionary)objectsDict.objectForKey(buildConfigurationListUUID)); if ( buildConfigurationList != null ) { if ( buildConfigurationList.objectForKey("defaultConfigurationName") != null ) { target.defaultConfigurationName = buildConfigurationList.objectForKey("defaultConfigurationName").toString(); } NSObject[] buildConfigurationUUIDs = ((NSArray)buildConfigurationList.objectForKey("buildConfigurations")).getArray(); // Parse each build configurations. for ( NSObject buildConfigurationUUID : buildConfigurationUUIDs ) { BuildConfiguration buildConfiguration = new BuildConfiguration(objectsDict, buildConfigurationUUID.toString(), target.provisioningStyle.equals("Automatic")); target.buildConfiguration.put(buildConfiguration.name, buildConfiguration); } } project.projectTarget.put(targetName, target); } else if ( target.productType.equals("com.apple.product-type.framework" ) ) { } } } catch ( IOException ex ) { ex.printStackTrace(); project = null; } catch ( PropertyListFormatException ex ) { ex.printStackTrace(); project = null; } catch ( ParseException ex ) { ex.printStackTrace(); project = null; } catch ( ParserConfigurationException ex ) { ex.printStackTrace(); project = null; } catch ( SAXException ex ) { ex.printStackTrace(); project = null; } catch ( InterruptedException ex ) { ex.printStackTrace(); project = null; } return project; } } ================================================ FILE: src/main/java/au/com/rayh/XcodeSchemeFileFilter.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package au.com.rayh; import java.io.File; import java.io.FileFilter; import java.io.Serializable; /** * @author Kazuhide Takahashi */ public class XcodeSchemeFileFilter implements FileFilter, Serializable { public boolean accept(File pathname) { return pathname.isFile() && pathname.getName().endsWith(".xcscheme"); } } ================================================ FILE: src/main/java/au/com/rayh/XcodeTestSummariesParser.java ================================================ package au.com.rayh; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.text.ParseException; import hudson.FilePath; import com.dd.plist.NSDictionary; import com.dd.plist.NSArray; import com.dd.plist.NSNumber; import com.dd.plist.NSObject; import com.dd.plist.PropertyListParser; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import au.com.rayh.report.TestCase; import au.com.rayh.report.TestError; import au.com.rayh.report.TestFailure; import au.com.rayh.report.TestSuite; /** * Summary of test results output by xcodebuild Analyze "TestSummaries.plist" to generate a JUnit compatible XML file. * @author Kazuhide Takahashi */ public class XcodeTestSummariesParser { private FilePath testReportsDir; //private static Pattern ASSERTION_FAILURE = Pattern.compile("(Assertion Failure: .*?)\\{\\(\\n(.*?)\\n\\)\\}", Pattern.DOTALL); private static Pattern FAILED_MESSAGE = Pattern.compile("(failed: .*?)\\n\\((.*?)\\n\\)", Pattern.DOTALL); public XcodeTestSummariesParser(FilePath workspace) throws IOException, InterruptedException { super(); testReportsDir = workspace.child("test-reports"); testReportsDir.mkdirs(); } private void writeTestReport(TestSuite currentTestSuite) throws IOException, InterruptedException, JAXBException { try (OutputStream testReportOutputStream = outputForSuite(currentTestSuite)) { JAXBContext jaxbContext; Thread t = Thread.currentThread(); ClassLoader orig = t.getContextClassLoader(); t.setContextClassLoader(XcodeTestSummariesParser.class.getClassLoader()); try { jaxbContext = JAXBContext.newInstance(TestSuite.class); } finally { t.setContextClassLoader(orig); } Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.marshal(currentTestSuite, testReportOutputStream); } } protected OutputStream outputForSuite(TestSuite currentTestSuite) throws IOException, InterruptedException { return testReportsDir.child("TEST-" + currentTestSuite.getName() + ".xml").write(); } private static void addFailureSummaries(NSObject[] failureSummaries, TestCase currentTestCase) { for ( NSObject object:failureSummaries ) { NSDictionary failureSummarie = (NSDictionary)object; boolean performanceFailure = ((NSNumber)failureSummarie.objectForKey("PerformanceFailure")).boolValue(); if ( !performanceFailure ) { TestFailure failure; String message = failureSummarie.objectForKey("Message").toString(); Matcher m = FAILED_MESSAGE.matcher(message); if ( m.matches() ) { String errorMessage = m.group(1); String stackTrace = m.group(2); failure = new TestFailure(errorMessage, stackTrace); } else { String fileName = failureSummarie.objectForKey("FileName").toString(); String lineNumber = failureSummarie.objectForKey("LineNumber").toString(); failure = new TestFailure(message + "\n at File: " + fileName + "\n Line number: " + lineNumber, "No stacktrace here."); } currentTestCase.getFailures().add(failure); } } } /* private static void addActivitySummaries(NSObject[] activitySummaries, TestCase currentTestCase) { for ( NSObject object:activitySummaries ) { NSDictionary summarie = (NSDictionary)object; NSObject value = summarie.objectForKey("Title"); if ( value != null ) { String title = value.toString(); Matcher m = ASSERTION_FAILURE.matcher(title); if ( m.matches() ) { String errorLocation = m.group(1); String errorMessage = m.group(2); TestFailure failure = new TestFailure(errorMessage, errorLocation); currentTestCase.getFailures().add(failure); } } } } */ /** * @param tests An array of NSDictionaries containing the results of subtests. * @param parentTestSuite An instance of the parent test result including this subtests. */ public void parseSubTests(NSObject[] tests, TestSuite parentTestSuite) throws ParseException, IOException, InterruptedException, JAXBException { for ( NSObject object:tests ) { NSDictionary test = (NSDictionary)object; Float duration = ((NSNumber)test.objectForKey("Duration")).floatValue(); String testName = test.objectForKey("TestName").toString(); String testIdentifier = test.objectForKey("TestIdentifier").toString(); String testObjectClass = test.objectForKey("TestObjectClass").toString(); NSObject value = test.objectForKey("Subtests"); if ( value == null ) { TestCase currentTestCase = new TestCase(parentTestSuite.getName(), testName); String testStatus = test.objectForKey("TestStatus").toString(); if ( testStatus.equals("Failure") ) { value = test.objectForKey("FailureSummaries"); if ( value != null ) { NSObject[] failureSummaries = ((NSArray)value).getArray(); addFailureSummaries(failureSummaries, currentTestCase); } /* value = test.objectForKey("ActivitySummaries"); if ( value != null ) { NSObject[] activitySummaries = ((NSArray)value).getArray(); addActivitySummaries(activitySummaries, currentTestCase); } */ currentTestCase.setTime(duration); parentTestSuite.getTestCases().add(currentTestCase); parentTestSuite.addFailure(); } else if ( testStatus.equals("Success") ) { currentTestCase.setTime(duration); parentTestSuite.getTestCases().add(currentTestCase); parentTestSuite.addTest(); } writeTestReport(parentTestSuite); } else { TestSuite currentTestSuite = new TestSuite(InetAddress.getLocalHost().getHostName(), testName, null); currentTestSuite.setDuration(duration); NSObject[] subTests = ((NSArray)value).getArray(); parseSubTests(subTests, currentTestSuite); } } } /** * @param testSummariesPlistFile The location of the TestSummaries.plist file output from Xcode. */ public void parseTestSummariesPlist(FilePath testSummariesPlistFile) { try { NSDictionary rootDict = (NSDictionary)PropertyListParser.parse(testSummariesPlistFile.read()); NSObject[] testableSummaries = ((NSArray)rootDict.objectForKey("TestableSummaries")).getArray(); for ( NSObject object:testableSummaries ) { NSDictionary testSummarie = (NSDictionary)object; String diagnosticsDirectory = testSummarie.objectForKey("DiagnosticsDirectory").toString(); String testName = testSummarie.objectForKey("TestName").toString(); String projectPath = testSummarie.objectForKey("ProjectPath").toString(); String targetName = testSummarie.objectForKey("TargetName").toString(); TestSuite currentTestSuite = new TestSuite(InetAddress.getLocalHost().getHostName(), testName, null); NSObject[] tests = ((NSArray)testSummarie.objectForKey("Tests")).getArray(); if ( tests != null ) { parseSubTests(tests, currentTestSuite); } } } catch ( Exception ex ) { ex.printStackTrace(); } } } ================================================ FILE: src/main/java/au/com/rayh/report/TestCase.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh.report; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; @XmlType(name="testcase") @XmlAccessorType(XmlAccessType.NONE) public class TestCase { @XmlAttribute String classname; @XmlAttribute String name; @XmlAttribute float time; @XmlElement(name="failure") List failures = new ArrayList<>(); @XmlElement(name="error") List errors = new ArrayList<>(); public TestCase() { } @SuppressFBWarnings("URF_UNREAD_FIELD") public TestCase(String classname, String name) { this.classname = classname; this.name = name; } public String getName() { return name; } public void setTime(float time) { this.time = time; } public float getTime() { return time; } public List getFailures() { return failures; } public List getErrors() { return errors; } } ================================================ FILE: src/main/java/au/com/rayh/report/TestError.java ================================================ /* * The MIT License * * Copyright (c) 2014 David Baker * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh.report; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; @XmlType(name="error") @XmlAccessorType(XmlAccessType.NONE) public class TestError { @XmlAttribute String message; @XmlAttribute String type; public TestError() { } public TestError(String message, String type) { this.message = message; this.type = type; } public String getMessage() { return message; } public String getType() { return type; } } ================================================ FILE: src/main/java/au/com/rayh/report/TestFailure.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh.report; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlValue; @XmlType(name="failure") @XmlAccessorType(XmlAccessType.NONE) public class TestFailure { @XmlAttribute String message; @SuppressFBWarnings("URF_UNREAD_FIELD") @XmlAttribute String type = "Failure"; @XmlValue String location; public TestFailure() { } public TestFailure(String message, String location) { this.message = message; this.location = location; } public String getMessage() { return message; } public String getLocation() { return location; } } ================================================ FILE: src/main/java/au/com/rayh/report/TestSuite.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh.report; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; @XmlRootElement(name="testsuite") @XmlAccessorType(XmlAccessType.NONE) public class TestSuite { @XmlAttribute int failures; @XmlAttribute int errors; @XmlAttribute String hostname; @XmlAttribute String name; @XmlAttribute int tests; @XmlAttribute float time; @XmlAttribute(name="timestamp") Date endTime; @XmlElement(name="testcase") List testcases = new ArrayList<>(); @XmlTransient Date startTime; HashMap testCasesHash = new HashMap (); public TestSuite() { } @SuppressFBWarnings({"EI_EXPOSE_REP2", "URF_UNREAD_FIELD"}) public TestSuite(String hostname, String name, Date startTime) { this.hostname = hostname; this.name = name; this.startTime = startTime; } public void setDuration(Float duration) { this.time = duration; } public HashMap getTestCasesHash() { return testCasesHash; } public void setTestCasesHash(HashMap testCasesHash) { this.testCasesHash = testCasesHash; } public int getFailures() { return failures; } public int getErrors() { return errors; } public int getTests() { return tests; } public void addFailure() { failures+=1; } public void addError() { errors+=1; } public void addTest() { tests+=1; } public String getName() { return name; } @SuppressFBWarnings("EI_EXPOSE_REP") public Date getStartTime() { return startTime; } @SuppressFBWarnings({"EI_EXPOSE_REP2", "URF_UNREAD_FIELD"}) public void setEndTime(Date endTime) { this.endTime = endTime; this.time = (endTime.getTime() - startTime.getTime())/1000f; } public List getTestCases() { return testcases; } } ================================================ FILE: src/main/java/hudson/plugins/xcode/XcodeInstallation.java ================================================ package hudson.plugins.xcode; import hudson.EnvVars; import hudson.Extension; import hudson.init.Initializer; import hudson.model.EnvironmentSpecific; import hudson.model.Node; import hudson.model.TaskListener; import hudson.slaves.NodeSpecific; import hudson.tools.ToolDescriptor; import hudson.tools.ToolInstallation; import hudson.tools.ToolProperty; import hudson.util.FormValidation; import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Logger; import static hudson.init.InitMilestone.EXTENSIONS_AUGMENTED; import java.util.logging.Level; /** * Information about Xcode installation. * * @author Kazuhide Takahashi */ public class XcodeInstallation extends ToolInstallation implements NodeSpecific, EnvironmentSpecific { /** * Constructor for XcodeInstallation. * * @param name Tool name (for example, "Xcode 9.3") * @param home Tool location (usually "/Applications/Xcode.app/Contents/Developer") * @param properties {@link java.util.List} of properties for this tool */ @DataBoundConstructor public XcodeInstallation(String name, String home, List> properties) { super(name, home, properties); } public static XcodeInstallation[] allInstallations() { Jenkins instance = Jenkins.getInstance(); if ( instance != null ) { DescriptorImpl descriptor = instance.getDescriptorByType(DescriptorImpl.class); if ( descriptor != null ) { XcodeInstallation[] installations = descriptor.getInstallations(); if ( installations != null ) { return installations; } } } return new XcodeInstallation[0]; } /** * getXcodebuild. * * @return {@link java.lang.String} that will be used to execute xcodebuild (e.g. "/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild") */ public String getXcodebuild() { return getHome() + "/usr/bin/xcodebuild"; } private static XcodeInstallation[] getInstallations(DescriptorImpl descriptor) { XcodeInstallation[] installations = null; try { installations = descriptor.getInstallations(); } catch (NullPointerException e) { installations = new XcodeInstallation[0]; } return installations; } public XcodeInstallation forNode(Node node, TaskListener log) throws IOException, InterruptedException { return new XcodeInstallation(getName(), translateFor(node, log), Collections.>emptyList()); } public XcodeInstallation forEnvironment(EnvVars environment) { return new XcodeInstallation(getName(), environment.expand(getHome()), Collections.>emptyList()); } @Override public DescriptorImpl getDescriptor() { Jenkins jenkinsInstance = Jenkins.getInstance(); if (jenkinsInstance == null) { /* Throw AssertionError exception to match behavior of Jenkins.getDescriptorOrDie */ throw new AssertionError("No Jenkins instance"); } return (DescriptorImpl) jenkinsInstance.getDescriptorOrDie(getClass()); } @Extension @Symbol("xcode") public static class DescriptorImpl extends ToolDescriptor { public DescriptorImpl() { load(); } @Override public String getDisplayName() { return "Xcode tools"; } @Override public boolean configure(StaplerRequest req, JSONObject json) throws FormException { setInstallations(req.bindJSONToList(clazz, json.get("tool")).toArray(new XcodeInstallation[0])); save(); return true; } public FormValidation doCheckHome(@QueryParameter File value) { Jenkins.getInstance().checkPermission(Jenkins.ADMINISTER); String path = value.getPath() + "/usr/bin/xcodebuild"; return FormValidation.validateExecutable(path); } public XcodeInstallation getInstallation(String name) { for(XcodeInstallation i : getInstallations()) { if(i.getName().equals(name)) { return i; } } return null; } } } ================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/config.groovy ================================================ package au.com.rayh.DeveloperProfile import java.security.GeneralSecurityException import java.security.cert.CertificateException f = namespace(lib.FormTagLib) st = namespace("jelly:stapler") def fileForm() { f.entry(title:_("*.developerprofile File"), field:"image") { raw("") } f.entry(title:_("Password"), field:"password") { f.password() } } def img = instance?.image if (img ==null) { fileForm() } else { f.entry(title:_("Contents")) {// show the certificates in the profile try { def certs = instance.certificates certs.each { c -> boolean valid=true; try { c.checkValidity(); } catch (CertificateException e) { valid = false; } div(class:valid?null:'error') { text(instance.getDisplayNameOf(c)) if (!valid) text("expired"); } } if (certs.isEmpty()) div(class:'error', "There's no certificate in this profile"); } catch (IOException e) { div(class:'error', "Not a developer profile or a wrong password: ${e.message}") } catch (GeneralSecurityException e) { div(class:'error', "Not a developer profile or a wrong password: ${e.message}") } } f.optionalBlock(title:_("Re-upload *.developerprofile File"),inline:true) { fileForm() } } st.include(page: "id-and-description", class: descriptor.clazz) ================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/config_ja.properties ================================================ *.developerprofile\ \ File=*.developerprofile \u30d5\u30a1\u30a4\u30eb Password=\u30d1\u30b9\u30ef\u30fc\u30c9 Contents=\u5185\u5bb9 Re-upload\ *.developerprofile\ File=*.developerprofile \u30d5\u30a1\u30a4\u30eb\u3092\u518d\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9 ================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/help-description.html ================================================
Any one-liner text to help you remember what this certificate is among other certificates. Jenkins will use this text when it wants you to select a certificate.
================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/help-description_ja.html ================================================
この証明書が何であるかを覚えておくための任意の一行のテキスト。 Jenkinsはこのテキストを使用して証明書を選択します。
================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/help-password.html ================================================
The password you set when you exported your developer profile.
================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/help-password_ja.html ================================================
開発者プロファイルをエクスポートしたときに設定したパスワード。
================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/help.html ================================================
Register your developer profile to Jenkins so that you can sign binaries built on Jenkins with your identities. See this document for how to export your developer profile from your XCode into a *.developerprofile file.
================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/help_ja.html ================================================
開発者プロファイルをJenkinsに登録しておくと、Jenkinsでビルドされたバイナリに自分のIDで署名することができます。 詳しくは このドキュメント を参照して、どのようにしてXcodeから開発者プロフィール *.developerprofile をエクスポートするかを調べます。
================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfile/upload.groovy ================================================ package au.com.rayh.DeveloperProfile """
Developer Profile:   """ ================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfileLoader/config.jelly ================================================ ]]>
${%The 'Configure System' keychain information is used but this is a deprecated method.} ${%From now on, please move keychain information to 'Credentials' instead of 'Configure System' and use it.}
================================================ FILE: src/main/resources/au/com/rayh/DeveloperProfileLoader/config_ja.properties ================================================ Developer\ Profile=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB Import\ into\ existing\ Keychain=\u65E2\u5B58\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u30A4\u30F3\u30DD\u30FC\u30C8 Target\ keychain=\u5BFE\u8C61\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 none\ (specify\ one\ below)=\u672A\u9078\u629E (\u6B21\u3067\u6307\u5B9A) Keychain\ path=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 The\ path\ of\ the\ keychain\ to\ use\ to\ sign\ the\ IPA.=.ipa\u306B\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u884C\u306A\u3046\u306E\u306B\u4F7F\u7528\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 Keychain\ password=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 The\ password\ to\ use\ to\ unlock\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30ED\u30C3\u30AF\u3092\u89E3\u9664\u3059\u308B\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 Specify\ the\ developer\ profile\ to\ import\ into\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A none=\u672A\u9078\u629E specify\ one\ below=\u6B21\u3067\u6307\u5B9A Developer\ Profile\ ID=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306EID Specify\ the\ ID\ of\ the\ developer\ profile\ to\ import\ into\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306EID\u3092\u6307\u5B9A The\ globally\ configured\ keychain\ to\ import\ developer\ profile.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u305F\u3081\u306E\u30B7\u30B9\u30C6\u30E0\u8A2D\u5B9A\u3067\u8A2D\u5B9A\u3055\u308C\u305F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 Keychain\ path\ to\ import\ developer\ profile.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 Password\ to\ unlock\ keychain\ importing\ developer\ profile.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3059\u308B\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 Export\ keychain\ info=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8 Yes=\u306F\u3044 Set\ the\ path\ and\ password\ of\ the\ key\ chain\ that\ imported\ the\ developer\ profile\ into\ the\ environment\ variable.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3057\u305F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u3068\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u74B0\u5883\u5909\u6570\u306B\u8A2D\u5B9A\u3057\u307E\u3059\u3002 The\ 'Configure\ System'\ keychain\ information\ is\ used\ but\ this\ is\ a\ deprecated\ method.=\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u60C5\u5831\u304C\u4F7F\u308F\u308C\u3066\u3044\u307E\u3059\u304C\u3001\u73FE\u5728\u306F\u3053\u308C\u306F\u975E\u63A8\u5968\u306E\u65B9\u6CD5\u3067\u3059\u3002 From\ now\ on,\ please\ move\ keychain\ information\ to\ 'Credentials'\ instead\ of\ 'Configure\ System'\ and\ use\ it.=\u4ECA\u5F8C\u306F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u306F\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u3067\u306F\u306A\u304F\u300C\u8A8D\u8A3C\u60C5\u5831\u300D\u306B\u8A2D\u5B9A\u3057\u3066\u3001\u305D\u308C\u3092\u5229\u7528\u3059\u308B\u3088\u3046\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 The\ combination\ of\ path\ and\ password\ defined\ in\ 'Credentials'\ for\ unlocking\ the\ keychain\ that\ imports\ the\ developer\ profile.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3059\u308B\u305F\u3081\u306E\u300C\u8A8D\u8A3C\u60C5\u5831\u300D\u3067\u5B9A\u7FA9\u3055\u308C\u305F\u3001\u30D1\u30B9\u3068\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u7D44\u307F\u5408\u308F\u305B\u3002 ================================================ FILE: src/main/resources/au/com/rayh/ExportIpa/config.jelly ================================================ ]]>
================================================ FILE: src/main/resources/au/com/rayh/ExportIpa/config_ja.properties ================================================ Archive\ directory=\u30a2\u30fc\u30ab\u30a4\u30d6\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea Specify\ the\ location\ of\ the\ path\ to\ read\ the\ Archive\ for\ exporting\ the\ IPA\ file.=IPA\u30d5\u30a1\u30a4\u30eb\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3059\u308b\u305f\u3081\u306eArchive\u3092\u8aad\u307f\u8fbc\u3080\u30d1\u30b9\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002 General\ export\ settings=\u4e00\u822c\u7684\u306a\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u8a2d\u5b9a Xcode\ Tools\ Version=Xcode tools\u306e\u30d0\u30fc\u30b8\u30e7\u30f3 System\ Default=\u30b7\u30b9\u30c6\u30e0\u306e\u8a2d\u5b9a Export\ method=\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u306e\u65b9\u6cd5 The\ export\ method\ of\ the\ .app\ to\ generate\ the\ .ipa\ file.\ Should\ be\ one\ in\ 'development',\ 'ad-hoc',\ 'enterprise'\ or\ 'app-store'.=.app\u304b\u3089.ipa\u3092\u751f\u6210\u3059\u308b\u969b\u306e\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u65b9\u6cd5\u3092'development'\u3001'ad-hoc'\u3001'enterprise'\u3001'app-store'\u306e\u3044\u305a\u308c\u304b\u3067\u6307\u5b9a\u3057\u307e\u3059\u3002 .ipa\ filename\ pattern=.ipa\u30d5\u30a1\u30a4\u30eb\u540d\u306e\u30d1\u30bf\u30fc\u30f3 A\ pattern\ for\ the\ ipa\ file\ name.\ You\ may\ use=.ipa\u30d5\u30a1\u30a4\u30eb\u540d\u306e\u30d1\u30bf\u30fc\u30f3 and=\u305d\u3057\u3066 in\ this\ string=\u304c\u4f7f\u3048\u307e\u3059\u3002 Output\ directory=\u51fa\u529b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea The\ output\ directory\ for\ the\ .ipa\ file,\ relative\ to\ the\ build\ directory.=.ipa\u30d5\u30a1\u30a4\u30eb\u306e\u51fa\u529b\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u30d3\u30eb\u30c9\u4f5c\u696d\u7528\u30c7\u30a3\u30ec\u30af\u30c8\u30ea(build)\u304b\u3089\u306e\u76f8\u5bfe\u30d1\u30b9\u3067\u6307\u5b9a\u3057\u307e\u3059\u3002 Manifest\ Plist\ URL=Manifest Plist\u306eURL The\ base\ URL\ to\ use\ to\ create\ a\ Manifest\ Plist.\ If\ omitted\ no\ Manifest\ Plist\ will\ be\ generated=Manifest Plist\u306b\u5229\u7528\u3059\u308bURL\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002Manifest Plist\u304c\u4e0d\u8981\u306a\u3089\u8a2d\u5b9a\u3057\u307e\u305b\u3093\u3002 Code\ signing\ &\ OS\ X\ keychain\ options=\u30b3\u30fc\u30c9\u7f72\u540d\u3068\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u306e\u30aa\u30d7\u30b7\u30e7\u30f3 Code\ signing\ settings=\u30b3\u30fc\u30c9\u7f72\u540d\u306e\u8a2d\u5b9a Automatic\ Signing=\u81ea\u52d5\u7f72\u540d Read\ from\ Xcode\ Project=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306b\u5f93\u3046 Manual\ signing=\u624b\u52d5\u3067\u8a2d\u5b9a Development\ Team=\u958b\u767a\u8005\u30c1\u30fc\u30e0 Override\ the\ Development\ Team\ specified\ in\ the\ project.=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3067\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u958b\u767a\u8005\u30c1\u30fc\u30e0\u3092\u7121\u8996\u3057\u3066\u4e0a\u66f8\u304d\u3057\u307e\u3059\u3002 none=\u672a\u9078\u629e specify\ one\ below=\u6b21\u3067\u6307\u5b9a Development\ Team\ ID=\u958b\u767a\u8005\u30c1\u30fc\u30e0 The\ ID\ of\ the\ Apple\ development\ team\ to\ use\ to\ sign\ the\ IPA.=.ipa\u306b\u30b3\u30fc\u30c9\u7f72\u540d\u3059\u308b\u306e\u306b\u4f7f\u3046\u958b\u767a\u8005\u30c1\u30fc\u30e0ID\u3067\u3059\u3002 Provisioning\ Profiles=\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb Set\ a\ combination\ of\ 'Bundle\ ID'\ and\ 'UUID\ or\ Specifire'\ of\ 'provisioning\ profiles'\ used\ when\ exporting\ .ipa\ files.=ipa\u30d5\u30a1\u30a4\u30eb\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3059\u308b\u969b\u306b\u5229\u7528\u3059\u308bBundle ID\u3068\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u30d7\u30ed\u30d5\u30a1\u30a4\u30ebUUID\u307e\u305f\u306f\u8b58\u5225\u5b50\u306e\u7d44\u307f\u5408\u308f\u305b\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002 Bundle\ ID= The\ bundle\ identifier=Bundle ID for\ this\ provisioning\ profile=\u3053\u306e\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3068\u7d44\u307f\u3068\u306a\u308b\u30a2\u30d7\u30ea\u3092\u8b58\u5225\u3057\u307e\u3059\u3002 Provisioning\ profile\ UUID=\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb The\ UUID\ or\ Specifire\ of\ the\ provisioning\ profile\ associated\ to\ this\ bundle\ identifier.=Bundle ID\u3068\u7d44\u307f\u306b\u306a\u308b\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306eUUID\u307e\u305f\u306f\u8b58\u5225\u5b50\u3002 Unlock\ Keychain?=\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u3092\u30a2\u30f3\u30ed\u30c3\u30af Keychain=\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3 The\ globally\ configured\ keychain\ to\ unlock\ for\ this\ build.=\u3053\u306e\u30d3\u30eb\u30c9\u3067\u4f7f\u3046\u305f\u3081\u306b\u30ed\u30c3\u30af\u3092\u89e3\u9664\u3059\u308b\u30b0\u30ed\u30fc\u30d0\u30eb\u8a2d\u5b9a\u3055\u308c\u305f\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u3002 Keychain\ path=\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u306e\u30d1\u30b9 The\ path\ of\ the\ keychain\ to\ use\ to\ sign\ the\ IPA.=.ipa\u306b\u30b3\u30fc\u30c9\u7f72\u540d\u3092\u884c\u306a\u3046\u306e\u306b\u4f7f\u7528\u3059\u308b\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u306e\u30d1\u30b9\u3002 Keychain\ password=\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u306e\u30d1\u30b9\u30ef\u30fc\u30c9 The\ password\ to\ use\ to\ unlock\ the\ keychain.=\u30ad\u30fc\u30c1\u30a7\u30fc\u30f3\u306e\u30ed\u30c3\u30af\u3092\u89e3\u9664\u3059\u308b\u305f\u3081\u306e\u30d1\u30b9\u30ef\u30fc\u30c9\u3002 Advanced\ Xcode\ project\ options=Xcode\u306e\u4e0a\u7d1a\u30aa\u30d7\u30b7\u30e7\u30f3 Advanced\ project\ settings=\u4e0a\u7d1a\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u8a2d\u5b9a Xcode\ Schema\ File=Xcode Schema\u30d5\u30a1\u30a4\u30eb Needed\ if\ you\ want\ to\ compile\ for\ a\ specific\ schema\ instead\ of\ a\ target,\ or\ if\ you\ want\ to\ generate\ an\ archive\ or\ an\ IPA.=\u30bf\u30fc\u30b2\u30c3\u30c8\u3067\u306f\u306a\u304f\u7279\u5b9a\u306e\u30b9\u30ad\u30fc\u30de\u7528\u306b\u30b3\u30f3\u30d1\u30a4\u30eb\u3059\u308b\u5834\u5408\u3001\u307e\u305f\u306f\u30a2\u30fc\u30ab\u30a4\u30d6\u307e\u305f\u306f.ipa\u3092\u751f\u6210\u3059\u308b\u5834\u5408\u306b\u5fc5\u8981\u3067\u3059\u3002 Xcode\ Workspace\ File=Xcode Workspace\u30d5\u30a1\u30a4\u30eb Only\ needed\ if\ you\ want\ to\ compile\ a\ workspace\ instead\ of\ a\ project.=\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u4ee3\u308f\u308a\u306b\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u3092\u30b3\u30f3\u30d1\u30a4\u30eb\u3059\u308b\u5834\u5408\u306b\u306e\u307f\u5fc5\u8981\u3067\u3059\u3002 Xcode\ Project\ Directory=Xcode\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea Relative\ path\ within\ the\ workspace\ that\ contains\ the\ xcode\ project\ files.=xcode\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u542b\u3080\u30ef\u30fc\u30af\u30b9\u30da\u30fc\u30b9\u5185\u306e\u76f8\u5bfe\u30d1\u30b9\u3002 Xcode\ Project\ File=Xcode Project\u30d5\u30a1\u30a4\u30eb Only\ needed\ if\ there\ is\ more\ than\ one\ project\ file\ in\ the\ Xcode\ Project\ Directory=Xcode\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u306b\u8907\u6570\u306e\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u30d5\u30a1\u30a4\u30eb\u304c\u3042\u308b\u5834\u5408\u306b\u306e\u307f\u5fc5\u8981\u3067\u3059 Xcode\ Tools\ version.=Xcode tools\u306e\u30d0\u30fc\u30b8\u30e7\u30f3 if\ you\ need\ to\ override\ System\ Default=\u30b7\u30b9\u30c6\u30e0\u306e\u8a2d\u5b9a\u3092\u5909\u66f4\u3057\u305f\u3044\u5834\u5408 Manual\ signing?=\u624b\u52d5\u3067\u30b3\u30fc\u30c9\u7f72\u540d\u3092\u884c\u306a\u3046 Upload\ Bitcode?=Bitcode\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9 If\ checked,\ include\ Bitcode\ when\ exporting\ applications\ to\ IPA.=\u30c1\u30a7\u30c3\u30af\u3055\u308c\u3066\u3044\u308b\u306a\u3089\u3001\u51fa\u529b\u3059\u308bIPA\u30d5\u30a1\u30a4\u30eb\u306bBotcode\u3092\u542b\u3081\u307e\u3059\u3002 Upload\ Symbols?=\u30b7\u30f3\u30dc\u30eb\u3092\u30a2\u30c3\u30d7\u30ed\u30fc\u30c9 If\ checked,\ include\ symbols\ when\ exporting\ applications\ to\ IPA.=\u30c1\u30a7\u30c3\u30af\u3055\u308c\u3066\u3044\u308b\u306a\u3089\u3001\u51fa\u529b\u3059\u308bIPA\u30d5\u30a1\u30a4\u30eb\u306b\u30b7\u30f3\u30dc\u30eb\u3092\u542b\u3081\u307e\u3059\u3002 Compile\ Bitcode?=Bitcode\u3092\u30b3\u30f3\u30d1\u30a4\u30eb If\ checked,\ recompile\ from\ Bitcode\ when\ exporting\ the\ application\ to\ IPA.=\u30c1\u30a7\u30c3\u30af\u3055\u308c\u3066\u3044\u308b\u306a\u3089\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092IPA\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3059\u308b\u969b\u306bBitcode\u304b\u3089\u518d\u30b3\u30f3\u30d1\u30a4\u30eb\u3057\u307e\u3059\u3002 Thinning=\u6700\u9069\u5316 When\ doing\ Thinning,\ specify\ the\ target\ device\ for\ thinning.=\u6700\u9069\u5316\u3092\u884c\u306a\u3044\u305f\u3044\u5834\u5408\u306b\u306f\u3001\u5bfe\u8c61\u3068\u306a\u308b\u30c7\u30d0\u30a4\u30b9\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002 Display\ image\ URL=\u8868\u793a\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306eURL Specify\ the\ URL\ of\ the\ 57\ pixel\ size\ png\ image\ to\ be\ displayed\ in\ the\ IPA\ installation.=IPA\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u8868\u793a\u3059\u308b57\u30d4\u30af\u30bb\u30eb\u30b5\u30a4\u30ba\u306epng\u30a4\u30e1\u30fc\u30b8\u306eURL\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002 Full\ size\ image\ URL=\u30d5\u30eb\u30b5\u30a4\u30ba\u30a4\u30e1\u30fc\u30b8\u306eURL Specify\ the\ URL\ of\ the\ 512\ pixel\ size\ png\ image\ to\ be\ displayed\ in\ the\ IPA\ installation.=IPA\u306e\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u8868\u793a\u3059\u308b512\u30d4\u30af\u30bb\u30eb\u30b5\u30a4\u30ba\u306epng\u30a4\u30e1\u30fc\u30b8\u306eURL\u3092\u6307\u5b9a\u3057\u307e\u3059\u3002 Pack\ on\ demand\ resources?=\u30aa\u30f3\u30c7\u30de\u30f3\u30c9\u30ea\u30bd\u30fc\u30b9\u3092\u542b\u3081\u308b If\ checked,\ include\ on\ demand\ resource\ assets\ to\ the\ bundle.=\u30c1\u30a7\u30c3\u30af\u3055\u308c\u3066\u3044\u308b\u306a\u3089\u3001\u30aa\u30f3\u30c7\u30de\u30f3\u30c9\u30ea\u30bd\u30fc\u30b9\u30a2\u30bb\u30c3\u30c8\u3092\u30d0\u30f3\u30c9\u30eb\u306b\u542b\u3081\u307e\u3059\u3002 On\ demand\ resources\ asset\ URL=\u30aa\u30f3\u30c7\u30de\u30f3\u30c9\u30ea\u30bd\u30fc\u30b9\u306eURL Set\ the\ base\ URL\ for\ downloading\ resource\ assets\ when\ the\ resource\ asset\ is\ not\ included\ in\ the\ bundle\ in\ the\ application\ using\ the\ on\ demand\ resource.=\u30aa\u30f3\u30c7\u30de\u30f3\u30c9\u30ea\u30bd\u30fc\u30b9\u3092\u4f7f\u7528\u3057\u3066\u3044\u3066\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5185\u306e\u30d0\u30f3\u30c9\u30eb\u306b\u30ea\u30bd\u30fc\u30b9\u30a2\u30bb\u30c3\u30c8\u304c\u542b\u307e\u308c\u3066\u3044\u306a\u3044\u5834\u5408\u3001\u30ea\u30bd\u30fc\u30b9\u30a2\u30bb\u30c3\u30c8\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u305f\u3081\u306e\u30d9\u30fc\u30b9URL\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u3002 Application\ URL=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306eURL Asset\ pack\ URL=\u30a2\u30bb\u30c3\u30c8\u30d1\u30c3\u30af\u306eURL Specify\ the\ base\ URL\ of\ the\ downloading\ asset\ pack.=\u30a2\u30bb\u30c3\u30c8\u30d1\u30c3\u30af\u3092\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\u3059\u308b\u305f\u3081\u306e\u30d9\u30fc\u30b9URL Settings=\u8a2d\u5b9a Yes=\u306f\u3044 Strip\ Swift\ Symbols?=Swift\u306e\u30b7\u30f3\u30dc\u30eb\u3092\u524a\u9664 If\ checked,\ symbols\ be\ stripped\ from\ Swift\ libraries\ when\ exporting\ the\ application\ to\ IPA.=\u30c1\u30a7\u30c3\u30af\u3055\u308c\u3066\u3044\u308b\u306a\u3089\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092IPA\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3059\u308b\u969b\u306bIPA\u304b\u3089Swift\u306e\u30b7\u30f3\u30dc\u30eb\u3092\u524a\u9664\u3057\u307e\u3059\u3002 Copy\ provisioning\ profile=\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u3092\u30b3\u30d4\u30fc\u3059\u308b When\ the\ provisioning\ profile\ is\ specified\ in\ 'Provisioning\ profile\ UUID',\ copy\ the\ specified\ file\ to\ a\ predetermined\ place.=\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u304c\u300c\u30d7\u30ed\u30d3\u30b8\u30e7\u30cb\u30f3\u30b0\u30d7\u30ed\u30d5\u30a1\u30a4\u30ebUUID\u300d\u306b\u6307\u5b9a\u3055\u308c\u3066\u3044\u308b\u5834\u5408\u3001\u6307\u5b9a\u3055\u308c\u305f\u30d5\u30a1\u30a4\u30eb\u304c\u6240\u5b9a\u306e\u5834\u6240\u306b\u30b3\u30d4\u30fc\u3055\u308c\u307e\u3059\u3002 ================================================ FILE: src/main/resources/au/com/rayh/ExportIpa/help-archiveDir.html ================================================

Specify the location of the path (usually BUILD_DIR specified by xcodebuild) to read the Archive for exporting the IPA file.
Supports all macros and also environment and build variables from the Token Macro Plugin.
For example you can use the value :

${WORKSPACE}/build
================================================ FILE: src/main/resources/au/com/rayh/ExportIpa/help-archiveDir_ja.html ================================================

IPAファイルをエクスポートするためのArchiveを読み込むパス(通常はxcodebuildで指定したBUILD_DIR)の場所を指定します。
ビルド変数に 説明されている全ての環境変数とToken Macro Pluginで説明されている全てのマクロ>を使うことができます。
例えば次のような値を使用できます:

${WORKSPACE}/build
================================================ FILE: src/main/resources/au/com/rayh/GlobalConfigurationImpl/config.jelly ================================================
${%Although there is keychain information in 'Configure System', this is a deprecated method.} ${%From now on, please move keychain information to 'Credentials' instead of 'Configure System' and use it.}
================================================ FILE: src/main/resources/au/com/rayh/GlobalConfigurationImpl/config_ja.properties ================================================ Xcode\ Builder=Xcode\u30D3\u30EB\u30C9 xcodebuild\ executable\ path=xcodebuild\u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u306E\u30D1\u30B9 agvtool\ executable\ path=agvtool\u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u306E\u30D1\u30B9 xcrun\ executable\ path=xcrun\u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u306E\u30D1\u30B9 Apple\ Development\ Teams=Apple\u958B\u767A\u8005\u30C1\u30FC\u30E0 Team\ Name=\u958B\u767A\u8005\u30C1\u30FC\u30E0\u540D Development\ Team\ ID=\u958B\u767A\u8005\u30C1\u30FC\u30E0ID Keychains=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 Keychain\ Name=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u540D Keychain\ path=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 Keychain\ password=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 Add\ to\ keychain\ search\ path\ after\ build=\u30D3\u30EB\u30C9\u5F8C\u306B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30B5\u30FC\u30C1\u30D1\u30B9\u306B\u8FFD\u52A0 Yes=\u306F\u3044 No=\u3044\u3044\u3048 Default\ keychain=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 Saved\ development\ team\ configurations=\u4FDD\u5B58\u3055\u308C\u305F\u958B\u767A\u8005\u30C1\u30FC\u30E0\u306E\u8A2D\u5B9A An\ assigned\ name\ for\ identifying\ this\ Apple\ development\ team\ within\ Jenkins.=Jenkins\u3067\u3053\u306E\u958B\u767A\u8005\u30C1\u30FC\u30E0\u3092\u8B58\u5225\u3059\u308B\u305F\u3081\u306E\u540D\u524D The\ ID\ of\ the\ Apple\ development\ team\ to\ use\ to\ sign\ the\ IPA.=.ipa\u30D5\u30A1\u30A4\u30EB\u306B\u7F72\u540D\u3092\u3059\u308B\u305F\u3081\u306B\u4F7F\u3046Apple\u958B\u767A\u8005\u30C1\u30FC\u30E0\u306EID Saved\ keychain\ configurations=\u4FDD\u5B58\u3055\u308C\u305F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u8A2D\u5B9A An\ assigned\ name\ for\ identifying\ this\ keychain\ within\ Jenkins.=Jenkins\u3067\u3053\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u8B58\u5225\u3059\u308B\u305F\u3081\u306E\u540D\u524D The\ path\ of\ the\ keychain\ to\ use\ to\ sign\ the\ IPA.=.ipa\u30D5\u30A1\u30A4\u30EB\u306B\u7F72\u540D\u3092\u3059\u308B\u305F\u3081\u306B\u4F7F\u3046\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 The\ password\ to\ use\ to\ unlock\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3059\u308B\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 The\ keychain\ will\ be\ added\ to\ the\ keychain\ search\ path.\ This\ means\ it\ shows\ up\ in\ Keychain\ Access.app=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u30B5\u30FC\u30C1\u30D1\u30B9\u306B\u8FFD\u52A0\u3055\u308C\u307E\u3059\u3002\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306F\u300C\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u30A2\u30AF\u30BB\u30B9\u300D\u30A2\u30D7\u30EA\u306B\u8868\u793A\u3055\u308C\u308B\u3088\u3046\u306B\u306A\u308A\u307E\u3059 This\ will\ be\ the\ system\ default\ keychain=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u306A\u308A\u307E\u3059 Although\ there\ is\ keychain\ information\ in\ 'Configure\ System',\ this\ is\ a\ deprecated\ method.=\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u306B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u304C\u5B58\u5728\u3057\u307E\u3059\u304C\u3001\u73FE\u5728\u306F\u3053\u308C\u306F\u975E\u63A8\u5968\u306E\u65B9\u6CD5\u3067\u3059\u3002 From\ now\ on,\ please\ move\ keychain\ information\ to\ 'Credentials'\ instead\ of\ 'Configure\ System'\ and\ use\ it.=\u4ECA\u5F8C\u306F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u306F\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u3067\u306F\u306A\u304F\u300C\u8A8D\u8A3C\u60C5\u5831\u300D\u306B\u8A2D\u5B9A\u3057\u3066\u3001\u305D\u308C\u3092\u5229\u7528\u3059\u308B\u3088\u3046\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 ================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathBinding/config-variables.jelly ================================================ ================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathBinding/config-variables_ja.properties ================================================ Keychain\ Path\ Variable=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u3092\u4FDD\u5B58\u3059\u308B\u5909\u6570 Keychain\ Password\ Variable=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u4FDD\u5B58\u3059\u308B\u5909\u6570 In\ Search\ Path\ Variable=\u30D3\u30EB\u30C9\u5F8C\u306B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30B5\u30FC\u30C1\u30D1\u30B9\u306B\u8FFD\u52A0\u3059\u308B\u304B\u306E\u72B6\u614B\u3092\u4FDD\u5B58\u3059\u308B\u5909\u6570 # \u4EE5\u4E0B\u306F\u89AA(Credential Binding Plugin)\u306Ejelly\u304C\u6301\u3063\u3066\u3044\u308B\u306E\u3067\u305D\u3061\u3089\u306E\u4FEE\u6B63\u304C\u5FC5\u8981 Specific\ credentials=\u8A8D\u8A3C\u60C5\u5831\u3092\u6307\u5B9A Parameter\ expression=\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u8A55\u4FA1 ================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathBinding/help-inSearchPathVariable.html ================================================
Name of a variable that stores information on whether to set the keychain stored in the 'Credentials' to the search path.
Because values are stored in the environment variable of the name specified here, you can use the information stored in the 'Credentials' by shell script etc.
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathBinding/help-inSearchPathVariable_ja.html ================================================
認証情報に保存されているキーチェーンをサーチパスに設定するかどうかの情報を格納する変数の名前。
ここで指定された名前の環境変数に値が格納されるのでシェルスクリプトなどで認証情報に保存されている情報を利用することができます。
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathBinding/help-keychainPathVariable.html ================================================
Name of a variable that contains information about the keychain path stored in the 'Credentials'.
Because values are stored in the environment variable of the name specified here, you can use the information stored in the 'Credentials' by shell script etc.
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathBinding/help-keychainPathVariable_ja.html ================================================
認証情報に保存されているキーチェーンのパス情報を格納する変数の名前。
ここで指定された名前の環境変数に値が格納されるのでシェルスクリプトなどで認証情報に保存されている情報を利用することができます。
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathBinding/help-passwordVariable.html ================================================
Name of a variable that contains information about the keychain password stored in the 'Credentials'.
Because values are stored in the environment variable of the name specified here, you can use the information stored in the 'Credentials' by shell script etc.
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathBinding/help-passwordVariable_ja.html ================================================
認証情報に保存されているキーチェーンのパスワード情報を格納する変数の名前 。
ここで指定された名前の環境変数に値が格納されるのでシェルスクリプトなどで認証情報に保存されている情報を利用することができます。
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/credentials.jelly ================================================ ================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/credentials_ja.properties ================================================ Saved\ keychain\ configurations=\u4FDD\u5B58\u3055\u308C\u305F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u8A2D\u5B9A An\ assigned\ name\ for\ identifying\ this\ keychain\ within\ Jenkins.=Jenkins\u3067\u3053\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u8B58\u5225\u3059\u308B\u305F\u3081\u306E\u540D\u524D The\ path\ of\ the\ keychain\ to\ use\ to\ sign\ the\ IPA.=.ipa\u30D5\u30A1\u30A4\u30EB\u306B\u7F72\u540D\u3092\u3059\u308B\u305F\u3081\u306B\u4F7F\u3046\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 The\ password\ to\ use\ to\ unlock\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3059\u308B\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 The\ keychain\ will\ be\ added\ to\ the\ keychain\ search\ path.\ This\ means\ it\ shows\ up\ in\ Keychain\ Access.app=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u30B5\u30FC\u30C1\u30D1\u30B9\u306B\u8FFD\u52A0\u3055\u308C\u307E\u3059\u3002\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306F\u300C\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u30A2\u30AF\u30BB\u30B9\u300D\u30A2\u30D7\u30EA\u306B\u8868\u793A\u3055\u308C\u308B\u3088\u3046\u306B\u306A\u308A\u307E\u3059 This\ will\ be\ the\ system\ default\ keychain=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u306A\u308A\u307E\u3059 Keychains=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 Keychain\ Name=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u540D Keychain\ path=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 Keychain\ password=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 Add\ to\ keychain\ search\ path\ after\ build=\u30D3\u30EB\u30C9\u5F8C\u306B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30B5\u30FC\u30C1\u30D1\u30B9\u306B\u8FFD\u52A0 Yes=\u306F\u3044 No=\u3044\u3044\u3048 Default\ keychain=\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 ================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/help-description.html ================================================
Any one-liner text to help you remember what this certificate is among other certificates. Jenkins will use this text when it wants you to select a certificate.
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/help-description_ja.html ================================================
この証明書が何であるかを覚えておくための任意の一行のテキスト。 Jenkinsはこのテキストを使用して証明書を選択します。
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/help-id.html ================================================
An internal unique ID by which these credentials are identified from jobs and other configuration. Normally left blank, in which case an ID will be generated, which is fine for jobs created using visual forms. Useful to specify explicitly when using credentials from scripted configuration.
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/help-id_ja.html ================================================
この資格情報をジョブやその他の設定で識別するための内部固有IDです。
この項目を空白のままにした場合にはIDが自動生成されます。これはGUIインターフェイスを使用して作成されたジョブに適しています。
スクリプトなどで認証情報を使用するときには明示的に判りやすい文字列を設定した方が使い易いでしょう。
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/help-keychainPath.html ================================================
The path of the keychain to use to retrieve certificates to sign the package (example : ${HOME}/Library/Keychains/login.keychain)
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/help-keychainPath_ja.html ================================================
パッケージに署名するための証明書を取得するキーチェーンのパス。 (例: ${HOME}/Library/Keychains/login.keychain)
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/help-password.html ================================================
The password of the keychain to use to retrieve certificates to sign the package.
================================================ FILE: src/main/resources/au/com/rayh/KeychainPasswordAndPathImpl/help-password_ja.html ================================================
パッケージに署名するための証明書を取得するキーチェーンのパスワード。
================================================ FILE: src/main/resources/au/com/rayh/KeychainUnlockStep/config.jelly ================================================ ]]>
${%The 'Configure System' keychain information is used but this is a deprecated method.} ${%From now on, please move keychain information to 'Credentials' instead of 'Configure System' and use it.}
================================================ FILE: src/main/resources/au/com/rayh/KeychainUnlockStep/config_ja.properties ================================================ Developer\ Profile=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB Import\ into\ existing\ Keychain=\u65E2\u5B58\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u30A4\u30F3\u30DD\u30FC\u30C8 Target\ keychain=\u5BFE\u8C61\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 none\ (specify\ one\ below)=\u672A\u9078\u629E (\u6B21\u3067\u6307\u5B9A) Keychain\ path=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 The\ path\ of\ the\ keychain\ to\ use\ to\ sign\ the\ IPA.=.ipa\u306B\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u884C\u306A\u3046\u306E\u306B\u4F7F\u7528\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 Keychain\ password=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 The\ password\ to\ use\ to\ unlock\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30ED\u30C3\u30AF\u3092\u89E3\u9664\u3059\u308B\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 Specify\ the\ developer\ profile\ to\ import\ into\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A none=\u672A\u9078\u629E specify\ one\ below=\u6B21\u3067\u6307\u5B9A Developer\ Profile\ ID=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306EID Specify\ the\ ID\ of\ the\ developer\ profile\ to\ import\ into\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306B\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306EID\u3092\u6307\u5B9A The\ globally\ configured\ keychain\ to\ import\ developer\ profile.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u305F\u3081\u306E\u30B7\u30B9\u30C6\u30E0\u8A2D\u5B9A\u3067\u8A2D\u5B9A\u3055\u308C\u305F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 Keychain\ path\ to\ import\ developer\ profile.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 Password\ to\ unlock\ keychain\ importing\ developer\ profile.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3059\u308B\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 Export\ keychain\ info=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8 Yes=\u306F\u3044 Set\ the\ path\ and\ password\ of\ the\ key\ chain\ that\ imported\ the\ developer\ profile\ into\ the\ environment\ variable.=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3057\u305F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u3068\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u74B0\u5883\u5909\u6570\u306B\u8A2D\u5B9A\u3057\u307E\u3059\u3002 The\ 'Configure\ System'\ keychain\ information\ is\ used\ but\ this\ is\ a\ deprecated\ method.=\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u60C5\u5831\u304C\u4F7F\u308F\u308C\u3066\u3044\u307E\u3059\u304C\u3001\u73FE\u5728\u306F\u3053\u308C\u306F\u975E\u63A8\u5968\u306E\u65B9\u6CD5\u3067\u3059\u3002 From\ now\ on,\ please\ move\ keychain\ information\ to\ 'Credentials'\ instead\ of\ 'Configure\ System'\ and\ use\ it.=\u4ECA\u5F8C\u306F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u306F\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u3067\u306F\u306A\u304F\u300C\u8A8D\u8A3C\u60C5\u5831\u300D\u306B\u8A2D\u5B9A\u3057\u3066\u3001\u305D\u308C\u3092\u5229\u7528\u3059\u308B\u3088\u3046\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 The\ combination\ of\ path\ and\ password\ defined\ in\ 'Credentials'\ for\ unlocking\ the\ keychain\ used\ in\ this\ build.=\u3053\u306E\u30D3\u30EB\u30C9\u3067\u4F7F\u7528\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3059\u308B\u305F\u3081\u306E\u300C\u8A8D\u8A3C\u60C5\u5831\u300D\u3067\u5B9A\u7FA9\u3055\u308C\u305F\u3001\u30D1\u30B9\u3068\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u7D44\u307F\u5408\u308F\u305B\u3002 ================================================ FILE: src/main/resources/au/com/rayh/Messages.properties ================================================ # # The MIT License # # Copyright (c) 2011 Ray Yamamoto Hilton # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # XCodeBuilder.xcodebuildNotFound=Cannot find xcodebuild with the configured path {0}. XCodeBuilder.avgtoolNotFound=Cannot find agvtool with the configured path {0}. XCodeBuilder.buildDirMacroError=Failure while expanding macros and variables for buildDir. Error: {0} XCodeBuilder.symRootMacroError=Failure while expanding macros and variables for symRoot. Error: {0} XCodeBuilder.keychainNotConfigured=No global keychain or local keychain path/password was configured. XCodeBuilder.teamNotConfigured=No global development team or local team ID was configured, back to default automatic signing XCodeBuilder.unlockKeychainFailed=Unable to unlock the keychain. XCodeBuilder.xcrunNotFound=Cannot find xcrun with the configured path {0}. XCodeBuilder.cleaningBuildDir=Cleaning build directory: {0} XCodeBuilder.cleaningIPA=Cleaning up previously generated .ipa files XCodeBuilder.cleaningDSYM=Cleaning up previously generated .dSYM.zip files XCodeBuilder.cleaningTestReportsDir=Cleaning up test-reports : {0} XCodeBuilder.fetchingCFBundleShortVersionString=Fetching marketing version number (CFBundleShortVersionString) from project. XCodeBuilder.fetchingCFBundleVersion=Fetching technical version number (CFBundleVersion) from project. XCodeBuilder.invokeXcodebuild=Going to invoke xcodebuild: XCodeBuilder.packagingIPA=Packaging IPA XCodeBuilder.warningPackagingIPAForSimulatorSDK=WARNING: you are about to package an IPA but have selected a simulator SDK ({0}). The packaging will most probably fail. Check your configuration. XCodeBuilder.workingDir=Working directory is {0}. XCodeBuilder.xcode=Xcode XCodeBuilder.xcodeVersionNotFound=Check your Xcode installation. Jenkins cannot retrieve its version. XCodeBuilder.CFBundleShortVersionStringNotFound=No marketing version (CFBundleShortVersionString) found. XCodeBuilder.CFBundleShortVersionStringFound=Found marketing version (CFBundleShortVersionString): {0} XCodeBuilder.CFBundleShortVersionStringMacroError=Failure while expanding macros and variables for CFBundleShortVersionString. Error: {0} XCodeBuilder.CFBundleShortVersionStringUpdate=Updating marketing version (CFBundleShortVersionString) to: {0} XCodeBuilder.CFBundleShortVersionStringUpdateError=Could not set CFBundleShortVersionString to: {0} XCodeBuilder.CFBundleShortVersionStringUsed=Marketing version (CFBundleShortVersionString) used by Jenkins to produce the IPA: {0} XCodeBuilder.CFBundleShortVersionStringValue=Marketing version (CFBundleShortVersionString) found in project configuration: {0} XCodeBuilder.CFBundleVersionFound=Found technical version (CFBundleVersion): {0} XCodeBuilder.CFBundleVersionMacroError=Failure while expanding macros and variables for CFBundleVersion. Error: {0} XCodeBuilder.CFBundleVersionNotFound=No technical version found (CFBundleVersion) XCodeBuilder.CFBundleVersionUpdate=Updating technical version (CFBundleVersion) to: {0} XCodeBuilder.CFBundleVersionUpdateError=Could not set the CFBundleVersion to: {0} XCodeBuilder.CFBundleVersionUsed=Technical version (CFBundleVersion) used by Jenkins to produce the IPA: {0} XCodeBuilder.CFBundleVersionValue=Technical version (CFBundleVersion) found in project configuration: {0}. XCodeBuilder.NotExistingBuildDirectory=Build directory does not exist at {0}. Potential configuration issue. XCodeBuilder.NoArchivesInBuildDirectory=No xcarchive found under Build directory {0}. This could be a configuration or transcient error. XCodeBuilder.DebugInfoLineDelimiter=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\= XCodeBuilder.DebugInfoAvailableCertificates=\=\= Certificates available for the Codesign XCodeBuilder.DebugInfoCanFindCertificates=\=\= Can we find the requested developer certificate ? XCodeBuilder.DebugInfoAvailableSDKs=\=\= Available SDKs XCodeBuilder.DebugInfoAvailableSchemes=\=\= Available schemes XCodeBuilder.DebugInfoAvailableParameters=\=\= Available parameters XCodeBuilder.NoAvailableParameters=There are no available parameters or failed to parse the output of 'xcodebuild -help'. XCodeBuilder.agvtoolPathNotSet=Please specify the path to the agvtool executable (usually /usr/bin/agvtool) XCodeBuilder.xcodebuildPathNotSet=Please specify the path to the xcodebuild executable (usually /usr/bin/xcodebuild) XCodeBuilder.xcrunPathNotSet=Please specify the path to the xcrun executable (usually /usr/bin/xcrun) XCodeBuilder.zipFailed=Failed to zip *.dSYM into {0}-dSYM.zip XCodeBuilder.CFBundleIdentifierChanged=Changing CFBundleIdentifier from {0} to {1} XCodeBuilder.CFBundleIdentifierInfoPlistNotFound=No info.plist found: {0} XCodeBuilder.NoTargetsFoundInConfig=Unable to find any targets. XCodeBuilder.NoMatchingTargetsFound=No Targets found matching regular expression. XCodeBuilder.XcodeToolsDir=Xcode Tools directory is {0}. XCodeBuilder.FailedToGetVersionFromInfoPlist=Failed to get version from Info.plist: {0} XCodeBuilder.MarketingAndTechnicalVersionNotFound=You have to provide a value for either the marketing or technical version. Found neither. XCodeBuilder.PackagingArchiveToIpa=Packaging {0}.xcarchive => {1} XCodeBuilder.FailedToBuildIpa=Failed to build {0} XCodeBuilder.ArchivingDSYM=Archiving dSYM XCodeBuilder.NoDSYMFileFound=No dSYM file found in {0} ! XCodeBuilder.CreatingManifestPlist=Creating Manifest Plist => {0} XCodeBuilder.NoAppFoundInBuildDirectory=No .app or .appex found in build directory ({0}) XCodeBuilder.NeedSchema=When outputting archive or IPA, you need to specify a scheme. XCodeBuilder.AbortXcodeBuildFailed=xcodebuild failed. Check the logs for details XCodeBuilder.NeedOnDemandResourcesURL=If you do not include on demand resource assets in the bundle, you need a specify URL to download the resource pack. XCodeBuilder.CFBundleIdFailedGetInInfoPlist=Failed to read Bundle ID from ({0}): {1} XCodeBuilder.CFBundleIdReplaceWith=Bundle ID is replaced with: {0} XCodeBuilder.CFBundleIdFailedGetInMobileProvision=Failed to read Provisioning UUID from ({0}): {1} XCodeBuilder.ProfileUUIDReplaceWith=Provisioning UUID is replaced with: {0} XCodeBuilder.IpaExportMethodMuestBeOneOfTheFollowing=If buildIpa is checked, ipaExportMethod must be one of the following: {0} XCodeBuilder.BuildDirectory=buildDirectory: {0} XCodeBuilder.ReadSigningInfoFromProject=Read signing information from Xcode Project. XCodeBuilder.CouldNotReadInfoFrom=Could not read information from {0} XCodeBuilder.ReadInfoFromScheme=Read information from scheme {0} XCodeBuilder.CouldNotGetInfoFromScheme=Could not get information from scheme {0} XCodeBuilder.ReadProjectInfoFrom=Read project information from {0} XCodeBuilder.ReadInfoFromWorkspace=Read information from workspace {0} XCodeBuilder.UsingXcodeFileInfo=Using Xcode project file information {0} XCodeBuilder.CouldNotReadProjectInfoFrom=Could not read project information from {0} XCodeBuilder.CouldNotGetBuildConfig=Could not get build configuration ({0}) from {1} XCodeBuilder.UseingReleaseConfigFor=Useing Release configuration for build. XCodeBuilder.FoundDevelopmentTeamID=Found developmentTeamID ({0}) from {1} XCodeBuilder.SpecifyWorkspaceAlsoSetScheme=If you specify workspace, scheme setting is also required. XCodeBuilder.WorkspaceAndTargetCantSpecifySameTime=Workspace and target can not be specified at the same time. XCodeBuilder.SchemeAndTargetCantSpecifySameTime=Scheme and target can not be specified at the same time. XCodeBuilder.FailedToCopyMobileProvision=Failed to copy the mobile provision to the predetermined location: {0} XCodeBuilder.CopiedProvisioningProfile=Copied provisioning profile {0} in to the predetermined location {1} XCodeBuilder.CouldNotGetInfoFromMobileProvision=Could not get information from the provisioning profile: {0} XCodeBuilder.MultipleProjectInWorkSpace=Since there are multiple projects in the workspace, you must be specify the location of the target project as 'Xcode Project File'. XCodeBuilder.ParseingTestSummariesPlist=Parseing Test Summaries at {0}. XCodeBuilder.TestSummariesPlistNotExists=Test Summaries does not exist at {0}. XCodeBuilder.CleaningResultBundlePath=Cleaning up ResultBundlePath : {0} XCodeBuilder.UseDeprecatedKeychainInfo=The '[WARNING!] : Configure System' keychain information is used but this is a deprecated method.\nFrom now on, please set keychain information to 'Credencials' instead of 'Configure System' and use it. ################################################################################ #OSXKeychainBuildWrapper.restoreOSXKeychainsAfterBuildProcessAsDefinedInGlobalConfiguration=Restore OS X keychains after build process as defined in global configuration #OSXKeychainBuildWrapper.invalidDefaultKeychainName=Invalid default keychain name: {0} ExportIpa.ExportIpa=Export IPA ExportIpa.NeedToSpecifyArchiveLocation=To export an IPA file You need to specify the location where the archive was output in the Xcode Build step. DeveloperProfile.ImportDeveloperProfile=Import developer profile DeveloperProfile.NoDeveloperProfileConfigured=No Apple developer profile is configured DeveloperProfile.Installing=Installing {0} DeveloperProfileLoader.MustSpecifyKeychainPath=If you do not select the global configuration keychain, you must specify the keychain path. DeveloperProfileLoader.MustSpecifyKeychainPwd=If you do not select the global configuration keychain, you must specify the keychain password. DeveloperProfileLoader.MustSelectDeveloperProfile=Please select a registered developer profile under global configuration. DeveloperProfileLoader.KeychainPathOrPasswordIsBlank=macOS Keychain password or file path is empty DeveloperProfileLoader.NoKeychainInfoConfigured=No macOS Keychain info is configured KeychainPasswordAndPath.DisplayName=macOS Keychain password and path OSXKeychainUnclockStep.DisplayName=Unlock macOS X Keychain ================================================ FILE: src/main/resources/au/com/rayh/Messages_ja.properties ================================================ # # The MIT License # # Copyright (c) 2011 Ray Yamamoto Hilton # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # XCodeBuilder.xcodebuildNotFound=xcodebuild \u304C\u8A2D\u5B9A\u3055\u308C\u305F\u30D1\u30B9 {0} \u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 XCodeBuilder.avgtoolNotFound=agvtool \u304C\u8A2D\u5B9A\u3055\u308C\u305F\u30D1\u30B9 {0} \u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 XCodeBuilder.buildDirMacroError=buildDir \u306E\u30DE\u30AF\u30ED\u3084\u74B0\u5883\u5909\u6570\u306E\u5C55\u958B\u3067\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 Error: {0} XCodeBuilder.symRootMacroError=symRoot \u306E\u30DE\u30AF\u30ED\u3084\u74B0\u5883\u5909\u6570\u306E\u5C55\u958B\u3067\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 Error: {0} XCodeBuilder.keychainNotConfigured=\u30B0\u30ED\u30FC\u30D0\u30EB\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3084\u30ED\u30FC\u30AB\u30EB\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u3084\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 XCodeBuilder.teamNotConfigured=\u30B0\u30ED\u30FC\u30D0\u30EB\u958B\u767A\u8005\u30C1\u30FC\u30E0\u3084\u30ED\u30FC\u30AB\u30EB\u30C1\u30FC\u30E0ID\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u306E\u3067\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u81EA\u52D5\u7F72\u540D\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 XCodeBuilder.unlockKeychainFailed=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3067\u304D\u307E\u305B\u3093\u3002 XCodeBuilder.xcrunNotFound=xcrun \u304C\u8A2D\u5B9A\u3055\u308C\u305F\u30D1\u30B9 {0} \u306B\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 XCodeBuilder.cleaningBuildDir=\u30D3\u30EB\u30C9\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u30AF\u30EA\u30FC\u30F3\u30CA\u30C3\u30D7\u3057\u307E\u3059: {0} XCodeBuilder.cleaningIPA=\u4EE5\u524D\u306B\u751F\u6210\u3055\u308C\u305F .ipa \u30D5\u30A1\u30A4\u30EB\u3092\u30AF\u30EA\u30FC\u30F3\u30CA\u30C3\u30D7\u3057\u307E\u3059 XCodeBuilder.cleaningDSYM=\u4EE5\u524D\u306B\u751F\u6210\u3055\u308C\u305F .dSYM.zip \u30D5\u30A1\u30A4\u30EB\u3092\u30AF\u30EA\u30FC\u30F3\u30CA\u30C3\u30D7\u3057\u307E\u3059 XCodeBuilder.cleaningTestReportsDir=\u30C6\u30B9\u30C8\u30EC\u30DD\u30FC\u30C8\u3092\u30AF\u30EA\u30FC\u30F3\u30CA\u30C3\u30D7\u3057\u307E\u3059 : {0} XCodeBuilder.fetchingCFBundleShortVersionString=\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleShortVersionString) \u3092\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304B\u3089\u53D6\u5F97\u3057\u307E\u3059\u3002 XCodeBuilder.fetchingCFBundleVersion=\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleVersion) \u3092\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304B\u3089\u53D6\u5F97\u3057\u307E\u3059\u3002 XCodeBuilder.invokeXcodebuild=xcodebuild \u3092\u5B9F\u884C\u3057\u307E\u3059: XCodeBuilder.packagingIPA=IPA \u306B\u30D1\u30C3\u30B1\u30FC\u30B8\u30F3\u30B0\u3057\u307E\u3059 XCodeBuilder.warningPackagingIPAForSimulatorSDK=\u8B66\u544A: IPA \u3078\u306E\u30D1\u30C3\u30B1\u30FC\u30B8\u30F3\u30B0\u304C\u9078\u629E\u3055\u308C\u307E\u3057\u305F\u304C simulator SDK ({0}) \u304C\u9078\u629E\u3055\u308C\u3066\u3044\u308B\u306E\u3067\u30D1\u30C3\u30B1\u30FC\u30B8\u30F3\u30B0\u306B\u5931\u6557\u3057\u307E\u3059\u3002\u8A2D\u5B9A\u306E\u898B\u76F4\u3057\u3092\u884C\u306A\u3063\u3066\u304F\u3060\u3055\u3044\u3002 XCodeBuilder.workingDir=\u4F5C\u696D\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F: {0} XCodeBuilder.xcode=Xcode\u30D3\u30EB\u30C9 XCodeBuilder.xcodeVersionNotFound=\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3055\u308C\u3066\u3044\u308B Xcode \u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002Jenkins \u306F Xcode \u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 XCodeBuilder.CFBundleShortVersionStringNotFound=\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleShortVersionString) \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 XCodeBuilder.CFBundleShortVersionStringFound=\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleShortVersionString) \u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F: {0} XCodeBuilder.CFBundleShortVersionStringMacroError=CFBundleShortVersionString \u306E\u30DE\u30AF\u30ED\u3084\u74B0\u5883\u5909\u6570\u306E\u5C55\u958B\u3067\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 Error: {0} XCodeBuilder.CFBundleShortVersionStringUpdate=\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleShortVersionString) \u3092\u8A2D\u5B9A\u3057\u307E\u3059: {0} XCodeBuilder.CFBundleShortVersionStringUpdateError=CFBundleShortVersionString \u3092\u8A2D\u5B9A\u3067\u304D\u307E\u305B\u3093: {0} XCodeBuilder.CFBundleShortVersionStringUsed=\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleShortVersionString) \u306FJenkins\u304CIPA\u3092\u30D1\u30C3\u30B1\u30FC\u30B8\u3059\u308B\u306E\u306B\u4F7F\u308F\u308C\u307E\u3059: {0} XCodeBuilder.CFBundleShortVersionStringValue=\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleShortVersionString) \u3067\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u8A2D\u5B9A\u898B\u3064\u304B\u3063\u305F\u306E\u306F: {0} XCodeBuilder.CFBundleVersionFound=\u898B\u3064\u304B\u3063\u305F\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleVersion): {0} XCodeBuilder.CFBundleVersionMacroError=CFBundleVersion \u306E\u30DE\u30AF\u30ED\u3084\u74B0\u5883\u5909\u6570\u306E\u5C55\u958B\u3067\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 Error: {0} XCodeBuilder.CFBundleVersionNotFound=\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleVersion) \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002 XCodeBuilder.CFBundleVersionUpdate=\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleVersion) \u3092\u8A2D\u5B9A\u3057\u307E\u3059: {0} XCodeBuilder.CFBundleVersionUpdateError=CFBundleVersion \u3092\u8A2D\u5B9A\u3067\u304D\u307E\u305B\u3093: {0} XCodeBuilder.CFBundleVersionUsed=\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleVersion) \u306FJenkins\u304CIPA\u3092\u30D1\u30C3\u30B1\u30FC\u30B8\u3059\u308B\u306E\u306B\u4F7F\u308F\u308C\u307E\u3059: {0} XCodeBuilder.CFBundleVersionValue=\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3\u756A\u53F7 (CFBundleVersion) \u3067\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u8A2D\u5B9A\u306B\u898B\u3064\u304B\u3063\u305F\u306E\u306F: {0} XCodeBuilder.NotExistingBuildDirectory=\u30D3\u30EB\u30C9\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA {0} \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u305F\u3076\u3093\u9078\u5B9A\u306B\u554F\u984C\u304C\u3042\u308A\u307E\u3059\u3002 XCodeBuilder.NoArchivesInBuildDirectory=xcarchive \u304C\u30D3\u30EB\u30C9\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA {0} \u306B\u5B58\u5728\u3057\u307E\u305B\u3093\u3002\u8A2D\u5B9A\u306E\u30A8\u30E9\u30FC\u3082\u3057\u304F\u306F\u4E00\u6642\u7684\u306A\u554F\u984C\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 XCodeBuilder.DebugInfoLineDelimiter=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\=\= XCodeBuilder.DebugInfoAvailableCertificates=\=\= \u5229\u7528\u53EF\u80FD\u306A\u30C7\u30D9\u30ED\u30C3\u30D1\u30FC\u8A3C\u660E\u66F8 XCodeBuilder.DebugInfoCanFindCertificates=\=\= \u5FC5\u8981\u3068\u3059\u308B\u30C7\u30D9\u30ED\u30C3\u30D1\u30FC\u8A3C\u660E\u66F8\u306F\u898B\u5F53\u305F\u308A\u307E\u3059\u304B\uFF1F XCodeBuilder.DebugInfoAvailableSDKs=\=\= \u5229\u7528\u53EF\u80FD\u306ASDK XCodeBuilder.DebugInfoAvailableSchemes=\=\= \u5229\u7528\u53EF\u80FD\u306A\u30B9\u30AD\u30FC\u30E0 XCodeBuilder.DebugInfoAvailableParameters=\=\= \u5229\u7528\u53EF\u80FD\u306A\u30D1\u30E9\u30E1\u30FC\u30BF XCodeBuilder.agvtoolPathNotSet=agvtool \u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u306E\u30D1\u30B9\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (\u901A\u5E38\u306F /usr/bin/agvtool) XCodeBuilder.xcodebuildPathNotSet=xcodebuild \u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u306E\u30D1\u30B9\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (\u901A\u5E38\u306F /usr/bin/xcodebuild) XCodeBuilder.xcrunPathNotSet=xcrun \u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u306E\u30D1\u30B9\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044 (\u901A\u5E38\u306F /usr/bin/xcrun) XCodeBuilder.zipFailed=*.dSYM \u3092 {0}-dSYM.zip \u306Bzip\u5727\u7E2E\u3067\u304D\u307E\u305B\u3093 XCodeBuilder.CFBundleIdentifierChanged=CFBundleIdentifier \u3092 {0} \u304B\u3089 {1} \u306B\u5909\u66F4 XCodeBuilder.CFBundleIdentifierInfoPlistNotFound=info.plist \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: {0} XCodeBuilder.NoTargetsFoundInConfig=\u306A\u306B\u3082\u30BF\u30FC\u30B2\u30C3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 XCodeBuilder.NoMatchingTargetsFound=\u6B63\u898F\u8868\u73FE\u306B\u5408\u81F4\u3059\u308B\u30BF\u30FC\u30B2\u30C3\u30C8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 XCodeBuilder.XcodeToolsDir=Xcode Tools \u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306F {0}. XCodeBuilder.FailedToGetVersionFromInfoPlist=\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092Info.plist\u304B\u3089\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093: {0} XCodeBuilder.MarketingAndTechnicalVersionNotFound=\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u307E\u305F\u306F\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3\u306E\u3044\u305A\u308C\u304B\u306E\u5024\u3092\u4E0E\u3048\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u304C\u3069\u3061\u3089\u3082\u898B\u3064\u3051\u3089\u308C\u307E\u305B\u3093\u3002 XCodeBuilder.PackagingArchiveToIpa={0}.xcarchive \u304B\u3089 {1} \u3092\u30D1\u30C3\u30B1\u30FC\u30B8\u30F3\u30B0 XCodeBuilder.FailedToBuildIpa={0} \u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093 XCodeBuilder.ArchivingDSYM=dSYM \u3092\u30A2\u30FC\u30AB\u30A4\u30D6\u3057\u307E\u3059 XCodeBuilder.NoDSYMFileFound={0} \u306BdSYM\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093\uFF01 XCodeBuilder.CreatingManifestPlist=Manifest Plist {0} \u3092\u4F5C\u6210\u3057\u307E\u3059 XCodeBuilder.NoAppFoundInBuildDirectory=\u30D3\u30EB\u30C9\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA ({0}) \u306B .app \u3082 .appex \u3082\u898B\u3064\u304B\u308A\u307E\u305B\u3093 XCodeBuilder.NeedSchema=\u30A2\u30FC\u30AB\u30A4\u30D6\u3084IPA\u3092\u51FA\u529B\u3059\u308B\u5834\u5408\u306B\u306F\u30B9\u30AD\u30FC\u30E0\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 XCodeBuilder.AbortXcodeBuildFailed=Xcode\u30D3\u30EB\u30C9\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002\u8A73\u3057\u304F\u306F\u30ED\u30B0\u30D5\u30A1\u30A4\u30EB\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002 XCodeBuilder.NeedOnDemandResourcesURL=\u30AA\u30F3\u30C7\u30DE\u30F3\u30C9\u30EA\u30BD\u30FC\u30B9\u30A2\u30BB\u30C3\u30C8\u3092\u30D0\u30F3\u30C9\u30EB\u306B\u542B\u3081\u306A\u3044\u5834\u5408\u306F\u3001\u30EA\u30BD\u30FC\u30B9\u30D1\u30C3\u30AF\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3059\u308B\u305F\u3081\u306EURL\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 XCodeBuilder.CFBundleIdFailedGetInInfoPlist={0} \u304B\u3089\u306EBundle ID\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {1} XCodeBuilder.CFBundleIdReplaceWith=Bundle ID \u306F\u7F6E\u304D\u63DB\u3048\u3089\u308C\u307E\u3059: {0} XCodeBuilder.CFBundleIdFailedGetInMobileProvision={0} \u304B\u3089\u306E\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EBUUID\u306E\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {1} XCodeBuilder.ProfileUUIDReplaceWith=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EBUUID\u306F\u7F6E\u304D\u63DB\u3048\u3089\u308C\u307E\u3059: {0} XCodeBuilder.IpaExportMethodMuestBeOneOfTheFollowing=BuildIPA\u304C\u30C1\u30A7\u30C3\u30AF\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u306FipaExportMethod\u306F\u6B21\u306E\u3044\u305A\u308C\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093: {0} XCodeBuilder.BuildDirectory=\u30D3\u30EB\u30C9\u3092\u51FA\u529B\u3059\u308B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA: {0} XCodeBuilder.ReadSigningInfoFromProject=\u30B3\u30FC\u30C9\u7F72\u540D\u306E\u305F\u3081\u306E\u60C5\u5831\u3092Xcode\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304B\u3089\u8AAD\u307F\u53D6\u308A\u307E\u3059\u3002 XCodeBuilder.CouldNotReadInfoFrom={0} \u304B\u3089\u60C5\u5831\u3092\u8AAD\u307F\u53D6\u308C\u307E\u305B\u3093\u3002 XCodeBuilder.ReadInfoFromScheme=\u30B9\u30AD\u30FC\u30E0 {0} \u304B\u3089\u60C5\u5831\u3092\u8AAD\u307F\u8FBC\u307F\u307E\u3059\u3002 XCodeBuilder.CouldNotGetInfoFromScheme=\u30B9\u30AD\u30FC\u30E0 {0} \u304B\u3089\u60C5\u5831\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3002 XCodeBuilder.ReadProjectInfoFrom=\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u60C5\u5831\u3092 {0} \u304B\u3089\u8AAD\u307F\u8FBC\u307F\u307E\u3059\u3002 XCodeBuilder.ReadInfoFromWorkspace=\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9 {0} \u304B\u3089\u60C5\u5831\u3092\u8AAD\u307F\u8FBC\u307F\u307E\u3059\u3002 XCodeBuilder.UsingXcodeFileInfo=Xcode\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30D5\u30A1\u30A4\u30EB {0} \u306E\u60C5\u5831\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 XCodeBuilder.CouldNotReadProjectInfoFrom=\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u60C5\u5831\u3092 {0} \u304B\u3089\u60C5\u5831\u3092\u8AAD\u307F\u8FBC\u3081\u307E\u305B\u3093\u3002 XCodeBuilder.CouldNotGetBuildConfig=\u30D3\u30EB\u30C9\u8A2D\u5B9A({0})\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3002 XCodeBuilder.UseingReleaseConfigFor=Release\u8A2D\u5B9A\u3092\u30D3\u30EB\u30C9\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002 XCodeBuilder.FoundDevelopmentTeamID=developmentTeamID ({0}) \u3092 {1} \u3067\u898B\u3064\u3051\u307E\u3057\u305F\u3002 XCodeBuilder.SpecifyWorkspaceAlsoSetScheme=\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3092\u6307\u5B9A\u3059\u308B\u5834\u5408\u306F\u30B9\u30AD\u30FC\u30E0\u8A2D\u5B9A\u3082\u5FC5\u8981\u3067\u3059\u3002 XCodeBuilder.WorkspaceAndTargetCantSpecifySameTime=\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3068\u30BF\u30FC\u30B2\u30C3\u30C8\u3092\u540C\u6642\u306B\u6307\u5B9A\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002 XCodeBuilder.SchemeAndTargetCantSpecifySameTime=\u30B9\u30AD\u30FC\u30E0\u3068\u30BF\u30FC\u30B2\u30C3\u30C8\u3092\u540C\u6642\u306B\u6307\u5B9A\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002 XCodeBuilder.FailedToCopyMobileProvision=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u6240\u5B9A\u306E\u5834\u6240\u306B\u30B3\u30D4\u30FC\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F: {0} XCodeBuilder.CopiedProvisioningProfile=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB {0} \u3092\u6240\u5B9A\u306E\u5834\u6240 {1} \u306B\u30B3\u30D4\u30FC\u3057\u307E\u3057\u305F\u3002 XCodeBuilder.CouldNotGetInfoFromMobileProvision=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u60C5\u5831\u3092\u53D6\u5F97\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F: {0} XCodeBuilder.MultipleProjectInWorkSpace=\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306B\u306F\u8907\u6570\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C\u5B58\u5728\u3059\u308B\u305F\u3081\u3001\u30BF\u30FC\u30B2\u30C3\u30C8\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u5834\u6240\u3092\u300CXcode Project\u30D5\u30A1\u30A4\u30EB\u300D\u3068\u3057\u3066\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 XCodeBuilder.ParseingTestSummariesPlist=\u30C6\u30B9\u30C8\u7D50\u679C\u306E\u6982\u8981 {0} \u306E\u89E3\u6790\u3092\u884C\u3044\u307E\u3059\u3002 XCodeBuilder.TestSummariesPlistNotExists=\u30C6\u30B9\u30C8\u7D50\u679C\u306E\u6982\u8981 {0} \u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 XCodeBuilder.CleaningResultBundlePath=ResultBundlePath\u3092\u30AF\u30EA\u30FC\u30F3\u30CA\u30C3\u30D7\u3057\u307E\u3059: {0} XCodeBuilder.UseDeprecatedKeychainInfo=\u3010\u8B66\u544A\u3011: \u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u60C5\u5831\u304C\u4F7F\u308F\u308C\u3066\u3044\u307E\u3059\u304C\u3001\u73FE\u5728\u306F\u3053\u308C\u306F\u975E\u63A8\u5968\u306E\u65B9\u6CD5\u3067\u3059\u3002\n\u4ECA\u5F8C\u306F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u306F\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u3067\u306F\u306A\u304F\u300C\u8A8D\u8A3C\u60C5\u5831\u300D\u306B\u8A2D\u5B9A\u3057\u3066\u3001\u305D\u308C\u3092\u5229\u7528\u3059\u308B\u3088\u3046\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 ################################################################################ #OSXKeychainBuildWrapper.restoreOSXKeychainsAfterBuildProcessAsDefinedInGlobalConfiguration=\u30D3\u30EB\u30C9\u30D7\u30ED\u30BB\u30B9\u306E\u5F8C\u306BOS X\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30B0\u30ED\u30FC\u30D0\u30EB\u8A2D\u5B9A\u3067\u5B9A\u7FA9\u3055\u308C\u305F\u3082\u306E\u306B\u5FA9\u5143\u3059\u308B #OSXKeychainBuildWrapper.invalidDefaultKeychainName=\u30C7\u30D5\u30A9\u30EB\u30C8\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u540D\u524D\u304C\u9593\u9055\u3048\u3066\u3044\u307E\u3059: {0} ExportIpa.ExportIpa=IPA\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8 ExportIpa.NeedToSpecifyArchiveLocation=IPA\u30D5\u30A1\u30A4\u30EB\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3059\u308B\u306B\u306FXcode Build\u30B9\u30C6\u30C3\u30D7\u3067\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u51FA\u529B\u3057\u305F\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 DeveloperProfile.ImportDeveloperProfile=\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30A4\u30F3\u30DD\u30FC\u30C8 DeveloperProfile.NoDeveloperProfileConfigured=Apple\u958B\u767A\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 DeveloperProfile.Installing={0} \u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u307E\u3059 DeveloperProfileLoader.MustSpecifyKeychainPath=\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u9078\u629E\u3057\u306A\u3044\u306A\u3089\u3001\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u3092\u6307\u5B9A\u3057\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093\u3002 DeveloperProfileLoader.MustSpecifyKeychainPwd=\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3>\u3092\u9078\u629E\u3057\u306A\u3044\u306A\u3089\u3001\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3092\u6307\u5B9A\u3057\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093\u3002 DeveloperProfileLoader.MustSelectDeveloperProfile=\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u3067\u767B\u9332\u6E08\u307F\u306E\u30C7\u30D9\u30ED\u30C3\u30D1\u30FC\u30D7\u30ED\u30D5\u30A3\u30FC\u30EB\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002 DeveloperProfileLoader.KeychainPathOrPasswordIsBlank=macOS\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u304B\u30D5\u30A1\u30A4\u30EB\u306E\u30D1\u30B9\u304C\u7A7A\u767D\u3067\u3059 DeveloperProfileLoader.NoKeychainInfoConfigured=macOS\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 KeychainPasswordAndPath.DisplayName=macOS\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u30D1\u30B9 OSXKeychainUnclockStep.DisplayName=macOS\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3059\u308B ================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/config.jelly ================================================ ]]>
${%The 'Configure System' keychain information is used but this is a deprecated method.} ${%From now on, please move keychain information to 'Credentials' instead of 'Configure System' and use it.}
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/config_ja.properties ================================================ General\ build\ settings=\u4E00\u822C\u7684\u306A\u30D3\u30EB\u30C9\u8A2D\u5B9A Xcode\ Tools\ Version=Xcode tools\u306E\u30D0\u30FC\u30B8\u30E7\u30F3 Default=\u30C7\u30D5\u30A9\u30EB\u30C8 Target=\u30BF\u30FC\u30B2\u30C3\u30C8 Interpret\ As\ Regular\ Expression=\u6B63\u898F\u8868\u73FE\u3092\u8A55\u4FA1 Generate\ Archive?=\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u4F5C\u6210 No\ Console\ Log?=\u30B3\u30F3\u30BD\u30FC\u30EB\u30ED\u30B0\u3092\u51FA\u529B\u3057\u306A\u3044 Logfile\ Output\ directory=\u30ED\u30B0\u30D5\u30A1\u30A4\u30EB\u306E\u51FA\u529B\u5148 Configuration= Development\ Team=\u958B\u767A\u8005\u30C1\u30FC\u30E0 Development\ Team\ ID=\u958B\u767A\u8005\u30C1\u30FC\u30E0\u306EID Pack\ application,\ build\ and\ sign\ .ipa?=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092\u7F72\u540D\u3001\u30D1\u30C3\u30AF\u3057\u3066.ipa\u3092\u4F5C\u6210 Export\ Settings=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u306E\u8A2D\u5B9A Export\ method=\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u306E\u65B9\u6CD5 .ipa\ filename\ pattern=.ipa\u30D5\u30A1\u30A4\u30EB\u540D\u306E\u30D1\u30BF\u30FC\u30F3 Output\ directory=\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA Provisioning\ Profiles=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB Bundle\ ID= UUID\ or\ Specifire=UUID\u307E\u305F\u306F\u8B58\u5225\u5B50 Code\ signing\ &\ OS\ X\ keychain\ options=\u30B3\u30FC\u30C9\u7F72\u540D\u3068\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30AA\u30D7\u30B7\u30E7\u30F3 New\ bundle\ ID=\u65B0\u3057\u3044Bundle ID Info.plist\ path=Info.plist\u306E\u30D1\u30B9 Unlock\ Keychain?=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF Keychain=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3 Keychain\ path=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9 Keychain\ password=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u30EF\u30FC\u30C9 Advanced\ Xcode\ build\ options=Xcode\u306E\u4E0A\u7D1A\u30AA\u30D7\u30B7\u30E7\u30F3 Clean\ test\ reports?=\u30C6\u30B9\u30C8\u7D50\u679C\u3092\u30AF\u30EA\u30FC\u30F3 Xcode\ Schema\ File=Xcode Schema\u30D5\u30A1\u30A4\u30EB SDK= SYMROOT= Custom\ xcodebuild\ arguments=xcodebuild\u306E\u8FFD\u52A0\u30D1\u30E9\u30E1\u30FC\u30BF\u30FC Xcode\ Workspace\ File=Xcode Workspace\u30D5\u30A1\u30A4\u30EB Xcode\ Project\ Directory=Xcode\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA Xcode\ Project\ File=Xcode Project\u30D5\u30A1\u30A4\u30EB Build\ output\ directory=\u30D3\u30EB\u30C9\u306E\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA Versioning=\u30D0\u30FC\u30B8\u30E7\u30F3\u64CD\u4F5C Provide\ version\ number\ and\ run\ avgtool?=avgtool\u3092\u4F7F\u7528\u3057\u3066\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u64CD\u4F5C Marketing\ version=\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u30D0\u30FC\u30B8\u30E7\u30F3 Technical\ version=\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3 Leave\ empty\ for\ all\ targets=\u4F55\u3082\u8A2D\u5B9A\u3057\u306A\u3044\u3068\u5168\u3066\u306E\u30BF\u30FC\u30B2\u30C3\u30C8 A\ pattern\ for\ the\ ipa\ file\ name.\ You\ may\ use=.ipa\u30D5\u30A1\u30A4\u30EB\u540D\u306E\u30D1\u30BF\u30FC\u30F3 and=\u305D\u3057\u3066 in\ this\ string=\u304C\u4F7F\u3048\u307E\u3059\u3002 Provisioning\ profile\ UUID=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306EUUID Settings=\u8A2D\u5B9A Clean\ before\ build?=\u30D3\u30EB\u30C9\u524D\u306B\u6D88\u53BB This\ will\ delete\ the\ build\ directories\ before\ invoking\ the\ build.=\u30D3\u30EB\u30C9\u3092\u5B9F\u884C\u3059\u308B\u524D\u306B\u30D3\u30EB\u30C9\u4F5C\u696D\u7528\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u6D88\u53BB\u3057\u307E\u3059 Yes=\u306F\u3044 Checking\ this\ option\ will\ prevent\ this\ build\ step\ from\ failing\ if\ xcodebuild\ exits\ with\ a\ non-zero\ return\ code.=\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u30AA\u30F3\u306A\u3089xcodebuild\u306E\u7D42\u4E86\u5024\u304C0\u4EE5\u5916\u3067\u3082\u51E6\u7406\u3092\u7D9A\u884C\u3057\u307E\u3059\u3002 Allow\ failing\ build\ results?=\u51E6\u7406\u306B\u5931\u6557\u3057\u3066\u3082\u7D9A\u884C Checking\ this\ option\ will\ generate\ an\ xcarchive\ of\ the\ specified\ scheme.\ A\ workspace\ and\ scheme\ are\ are\ also\ needed\ for\ archives=\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u30AA\u30F3\u306A\u3089\u6307\u5B9A\u3055\u308C\u305F\u30B9\u30AD\u30FC\u30E0\u306Excarchive\u304C\u751F\u6210\u3055\u308C\u307E\u3059\u3002 \u30A2\u30FC\u30AB\u30A4\u30D6\u306B\u306Fworkspace\u3068Schema\u3082\u5FC5\u8981\u3067\u3059\u3002 Checking\ this\ option\ will\ not\ log\ xcode\ build\ output\ to\ console\ output.=\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u30AA\u30F3\u306A\u3089xcodebuild\u304B\u3089\u306E\u30B3\u30F3\u30BD\u30FC\u30EB\u51FA\u529B\u3092\u30ED\u30B0\u306B\u8A18\u9332\u3057\u307E\u305B\u3093\u3002 Leave\ empty\ for\ Log\ to\ project-directory/logs.\ The\ output\ directory\ for\ the\ separate\ logfile,\ relative\ to\ the\ project-directory.=\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA/Logs\u306B\u30ED\u30B0\u3092\u8A18\u9332\u3059\u308B\u5834\u5408\u306F\u7A7A\u306E\u307E\u307E\u306B\u3057\u307E\u3059\u3002 \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u8D77\u70B9\u3068\u3057\u305F\u5225\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u30ED\u30B0\u3092\u51FA\u529B\u3057\u305F\u3044\u5834\u5408\u306B\u6307\u5B9A\u3057\u307E\u3059\u3002 This\ is\ the\ name\ of\ the\ configuration\ as\ defined\ in\ the\ Xcode\ project.=Xcode\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3067\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u308B\u30B3\u30F3\u30D5\u30A3\u30B0\u30EC\u30FC\u30B7\u30E7\u30F3\u306E\u540D\u524D\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002 Manual\ signing?=\u624B\u52D5\u3067\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u884C\u306A\u3046 Override\ the\ Development\ Team\ specified\ in\ the\ project.=\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u3067\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u958B\u767A\u8005\u30C1\u30FC\u30E0\u3092\u7121\u8996\u3057\u3066\u4E0A\u66F8\u304D\u3057\u307E\u3059\u3002 none=\u672A\u9078\u629E specify\ one\ below=\u6B21\u3067\u6307\u5B9A The\ ID\ of\ the\ Apple\ development\ team\ to\ use\ to\ sign\ the\ IPA.=.ipa\u306B\u30B3\u30FC\u30C9\u7F72\u540D\u3059\u308B\u306E\u306B\u4F7F\u3046\u958B\u767A\u8005\u30C1\u30FC\u30E0ID\u3067\u3059\u3002 Checking\ this\ option\ will\ create\ a\ .ipa\ for\ each\ .app\ found\ in\ the\ build\ directory.=\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u30AA\u30F3\u306A\u3089\u30D3\u30EB\u30C9\u4F5C\u696D\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3067\u307F\u3064\u304B\u3063\u305F\u5168\u3066\u306E.app\u3092.ipa\u306B\u3059\u3057\u307E\u3059\u3002 .ipa\ Export\ Settings=.ipa\u30D5\u30A1\u30A4\u30EB\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u8A2D\u5B9A The\ export\ method\ of\ the\ .app\ to\ generate\ the\ .ipa\ file.\ Should\ be\ one\ in\ 'development',\ 'ad-hoc',\ 'enterprise'\ or\ 'app-store'.=.app\u304B\u3089.ipa\u3092\u751F\u6210\u3059\u308B\u969B\u306E\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u65B9\u6CD5\u3092'development'\u3001'ad-hoc'\u3001'enterprise'\u3001'app-store'\u306E\u3044\u305A\u308C\u304B\u3067\u6307\u5B9A\u3057\u307E\u3059\u3002 The\ output\ directory\ for\ the\ .ipa\ file,\ relative\ to\ the\ build\ directory.=.ipa\u30D5\u30A1\u30A4\u30EB\u306E\u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u30D3\u30EB\u30C9\u4F5C\u696D\u7528\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA(build)\u304B\u3089\u306E\u76F8\u5BFE\u30D1\u30B9\u3067\u6307\u5B9A\u3057\u307E\u3059\u3002 Manifest\ Plist\ URL=Manifest Plist\u306EURL The\ base\ URL\ to\ use\ to\ create\ a\ Manifest\ Plist.\ If\ omitted\ no\ Manifest\ Plist\ will\ be\ generated=Manifest Plist\u306B\u5229\u7528\u3059\u308BURL\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002Manifest Plist\u304C\u4E0D\u8981\u306A\u3089\u8A2D\u5B9A\u3057\u307E\u305B\u3093\u3002 Set\ a\ combination\ of\ 'Bundle\ ID'\ and\ 'UUID\ or\ Specifire'\ of\ 'provisioning\ profiles'\ used\ when\ exporting\ .ipa\ files.=.ipa\u30D5\u30A1\u30A4\u30EB\u3092\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3059\u308B\u969B\u306B\u5229\u7528\u3059\u308BBundle ID\u3068\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EBUUID\u307E\u305F\u306F\u8B58\u5225\u5B50\u306E\u7D44\u307F\u5408\u308F\u305B\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002 The\ bundle\ identifier=Bundle ID for\ this\ provisioning\ profile=\u3053\u306E\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3068\u7D44\u307F\u3068\u306A\u308B\u30A2\u30D7\u30EA\u3092\u8B58\u5225\u3057\u307E\u3059\u3002 The\ UUID\ or\ Specifire\ of\ the\ provisioning\ profile\ associated\ to\ this\ bundle\ identifier.=Bundle ID\u3068\u7D44\u307F\u306B\u306A\u308B\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306EUUID\u307E\u305F\u306F\u8B58\u5225\u5B50\u3002 Code\ signing\ settings=\u30B3\u30FC\u30C9\u7F72\u540D\u306E\u8A2D\u5B9A Change\ bundle\ ID?=Bundle ID\u306E\u5909\u66F4 Path\ to\ Info.plist\ file\ to\ be\ modified\ with\ the\ new\ bundle\ ID=Bundle ID\u3092\u5909\u66F4\u3057\u305FInfo.plist\u30D5\u30A1\u30A4\u30EB\u306E\u51FA\u529B\u30D1\u30B9 The\ globally\ configured\ keychain\ to\ unlock\ for\ this\ build.=\u3053\u306E\u30D3\u30EB\u30C9\u3067\u4F7F\u3046\u305F\u3081\u306B\u30ED\u30C3\u30AF\u3092\u89E3\u9664\u3059\u308B\u30B0\u30ED\u30FC\u30D0\u30EB\u8A2D\u5B9A\u3055\u308C\u305F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3002 The\ path\ of\ the\ keychain\ to\ use\ to\ sign\ the\ IPA.=.ipa\u306B\u30B3\u30FC\u30C9\u7F72\u540D\u3092\u884C\u306A\u3046\u306E\u306B\u4F7F\u7528\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30D1\u30B9\u3002 The\ password\ to\ use\ to\ unlock\ the\ keychain.=\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u30ED\u30C3\u30AF\u3092\u89E3\u9664\u3059\u308B\u305F\u3081\u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u3002 Advanced\ build\ settings=\u4E0A\u7D1A\u30D3\u30EB\u30C9\u8A2D\u5B9A Needed\ if\ you\ want\ to\ compile\ for\ a\ specific\ schema\ instead\ of\ a\ target,\ or\ if\ you\ want\ to\ generate\ an\ archive\ or\ an\ IPA.=\u30BF\u30FC\u30B2\u30C3\u30C8\u3067\u306F\u306A\u304F\u7279\u5B9A\u306E\u30B9\u30AD\u30FC\u30DE\u7528\u306B\u30B3\u30F3\u30D1\u30A4\u30EB\u3059\u308B\u5834\u5408\u3001\u307E\u305F\u306F\u30A2\u30FC\u30AB\u30A4\u30D6\u307E\u305F\u306F.ipa\u3092\u751F\u6210\u3059\u308B\u5834\u5408\u306B\u5FC5\u8981\u3067\u3059\u3002 Leave\ empty\ for\ default\ SDK=\u30C7\u30D5\u30A9\u30EB\u30C8\u306ESDK\u3092\u4F7F\u3046\u5834\u5408\u306B\u306F\u7A7A\u767D\u306E\u307E\u307E\u306B\u3057\u307E\u3059\u3002 Leave\ empty\ for\ default\ SYMROOT=\u30C7\u30D5\u30A9\u30EB\u30C8\u306ESYMROOT\u3092\u4F7F\u3046\u5834\u5408\u306B\u306F\u7A7A\u767D\u306E\u307E\u307E\u306B\u3057\u307E\u3059\u3002 Additional\ xcodebuild\ arguments=xcodebuild\u306B\u8FFD\u52A0\u3059\u308B\u5F15\u6570 Only\ needed\ if\ you\ want\ to\ compile\ a\ workspace\ instead\ of\ a\ project.=\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u4EE3\u308F\u308A\u306B\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3092\u30B3\u30F3\u30D1\u30A4\u30EB\u3059\u308B\u5834\u5408\u306B\u306E\u307F\u5FC5\u8981\u3067\u3059\u3002 Relative\ path\ within\ the\ workspace\ that\ contains\ the\ xcode\ project\ files.=xcode\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30D5\u30A1\u30A4\u30EB\u3092\u542B\u3080\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u5185\u306E\u76F8\u5BFE\u30D1\u30B9\u3002 Only\ needed\ if\ there\ is\ more\ than\ one\ project\ file\ in\ the\ Xcode\ Project\ Directory=Xcode\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u8907\u6570\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308B\u5834\u5408\u306B\u306E\u307F\u5FC5\u8981\u3067\u3059 The\ value\ to\ use\ for\ the\ BUILD_DIR\ setting.=BUILD_DIR\u8A2D\u5B9A\u306B\u4F7F\u7528\u3059\u308B\u5024\u3002 Checking\ this\ option\ will\ run\ avgtool\ and\ update\ the\ CFBundleVersion\ and\ CFBundleVersionShortString.= The\ value\ to\ use\ for\ CFBundleShortVersionString.\ Leave\ blank\ to\ use\ project's\ marketing\ number.=CFBundleShortVersionString\u306B\u4F7F\u7528\u3059\u308B\u5024\u3002 \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u4F7F\u7528\u3059\u308B\u306B\u306F\u7A7A\u767D\u306E\u307E\u307E\u306B\u3057\u307E\u3059\u3002 The\ value\ to\ use\ for\ CFBundleVersion.\ Leave\ blank\ to\ use\ project's\ technical\ number.=CFBundleVersion\u306B\u4F7F\u7528\u3059\u308B\u5024\u3002 \u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u30C6\u30AF\u30CB\u30AB\u30EB\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u4F7F\u7528\u3059\u308B\u5834\u5408\u306F\u7A7A\u767D\u306E\u307E\u307E\u306B\u3057\u307E\u3059\u3002 System\ Default=\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A Automatic\ Signing=\u81EA\u52D5\u7F72\u540D Read\ from\ Xcode\ Project=\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306B\u5F93\u3046 Manual\ signing=\u624B\u52D5\u3067\u8A2D\u5B9A Xcode\ Tools\ version.=Xcode tools\u306E\u30D0\u30FC\u30B8\u30E7\u30F3 if\ you\ need\ to\ override\ System\ Default=\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u3092\u5909\u66F4\u3057\u305F\u3044\u5834\u5408 Provisioning\ profiles=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB Upload\ Bitcode?=Bitcode\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9 If\ checked,\ include\ Bitcode\ when\ exporting\ applications\ to\ IPA.=\u30C1\u30A7\u30C3\u30AF\u3055\u308C\u3066\u3044\u308B\u306A\u3089\u3001\u51FA\u529B\u3059\u308BIPA\u30D5\u30A1\u30A4\u30EB\u306BBotcode\u3092\u542B\u3081\u307E\u3059\u3002 Upload\ Symbols?=\u30B7\u30F3\u30DC\u30EB\u3092\u30A2\u30C3\u30D7\u30ED\u30FC\u30C9 If\ checked,\ include\ symbols\ when\ exporting\ applications\ to\ IPA.=\u30C1\u30A7\u30C3\u30AF\u3055\u308C\u3066\u3044\u308B\u306A\u3089\u3001\u51FA\u529B\u3059\u308BIPA\u30D5\u30A1\u30A4\u30EB\u306B\u30B7\u30F3\u30DC\u30EB\u3092\u542B\u3081\u307E\u3059\u3002 Compile\ Bitcode?=Bitcode\u3092\u30B3\u30F3\u30D1\u30A4\u30EB If\ checked,\ recompile\ from\ Bitcode\ when\ exporting\ the\ application\ to\ IPA.=\u30C1\u30A7\u30C3\u30AF\u3055\u308C\u3066\u3044\u308B\u306A\u3089\u3001\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092IPA\u306B\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3059\u308B\u969B\u306BBitcode\u304B\u3089\u518D\u30B3\u30F3\u30D1\u30A4\u30EB\u3057\u307E\u3059\u3002 Thinning=\u6700\u9069\u5316 When\ doing\ Thinning,\ specify\ the\ target\ device\ for\ thinning.=\u6700\u9069\u5316\u3092\u884C\u306A\u3044\u305F\u3044\u5834\u5408\u306B\u306F\u3001\u5BFE\u8C61\u3068\u306A\u308B\u30C7\u30D0\u30A4\u30B9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002 Display\ image\ URL=\u8868\u793A\u3059\u308B\u30A4\u30E1\u30FC\u30B8\u306EURL Specify\ the\ URL\ of\ the\ 57\ pixel\ size\ png\ image\ to\ be\ displayed\ in\ the\ IPA\ installation.=IPA\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3067\u8868\u793A\u3059\u308B57\u30D4\u30AF\u30BB\u30EB\u30B5\u30A4\u30BA\u306Epng\u30A4\u30E1\u30FC\u30B8\u306EURL\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002 Full\ size\ image\ URL=\u30D5\u30EB\u30B5\u30A4\u30BA\u30A4\u30E1\u30FC\u30B8\u306EURL Specify\ the\ URL\ of\ the\ 512\ pixel\ size\ png\ image\ to\ be\ displayed\ in\ the\ IPA\ installation.=IPA\u306E\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3067\u8868\u793A\u3059\u308B512\u30D4\u30AF\u30BB\u30EB\u30B5\u30A4\u30BA\u306Epng\u30A4\u30E1\u30FC\u30B8\u306EURL\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002 Pack\ on\ demand\ resources?=\u30AA\u30F3\u30C7\u30DE\u30F3\u30C9\u30EA\u30BD\u30FC\u30B9\u3092\u542B\u3081\u308B If\ checked,\ include\ on\ demand\ resource\ assets\ to\ the\ bundle.=\u30C1\u30A7\u30C3\u30AF\u3055\u308C\u3066\u3044\u308B\u306A\u3089\u3001\u30AA\u30F3\u30C7\u30DE\u30F3\u30C9\u30EA\u30BD\u30FC\u30B9\u30A2\u30BB\u30C3\u30C8\u3092\u30D0\u30F3\u30C9\u30EB\u306B\u542B\u3081\u307E\u3059\u3002 On\ demand\ resources\ asset\ URL=\u30AA\u30F3\u30C7\u30DE\u30F3\u30C9\u30EA\u30BD\u30FC\u30B9\u306EURL Set\ the\ base\ URL\ for\ downloading\ resource\ assets\ when\ the\ resource\ asset\ is\ not\ included\ in\ the\ bundle\ in\ the\ application\ using\ the\ on\ demand\ resource.=\u30AA\u30F3\u30C7\u30DE\u30F3\u30C9\u30EA\u30BD\u30FC\u30B9\u3092\u4F7F\u7528\u3057\u3066\u3044\u3066\u3001\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u5185\u306E\u30D0\u30F3\u30C9\u30EB\u306B\u30EA\u30BD\u30FC\u30B9\u30A2\u30BB\u30C3\u30C8\u304C\u542B\u307E\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u3001\u30EA\u30BD\u30FC\u30B9\u30A2\u30BB\u30C3\u30C8\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3059\u308B\u305F\u3081\u306E\u30D9\u30FC\u30B9URL\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002 Application\ URL=\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306EURL Asset\ pack\ URL=\u30A2\u30BB\u30C3\u30C8\u30D1\u30C3\u30AF\u306EURL Specify\ the\ base\ URL\ of\ the\ downloading\ asset\ pack.=\u30A2\u30BB\u30C3\u30C8\u30D1\u30C3\u30AF\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9\u3059\u308B\u305F\u3081\u306E\u30D9\u30FC\u30B9URL Strip\ Swift\ Symbols?=Swift\u306E\u30B7\u30F3\u30DC\u30EB\u3092\u524A\u9664 If\ checked,\ symbols\ be\ stripped\ from\ Swift\ libraries\ when\ exporting\ the\ application\ to\ IPA.=\u30C1\u30A7\u30C3\u30AF\u3055\u308C\u3066\u3044\u308B\u306A\u3089\u3001\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092IPA\u306B\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3059\u308B\u969B\u306BIPA\u304B\u3089Swift\u306E\u30B7\u30F3\u30DC\u30EB\u3092\u524A\u9664\u3057\u307E\u3059\u3002 Copy\ provisioning\ profile=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3092\u30B3\u30D4\u30FC\u3059\u308B When\ the\ provisioning\ profile\ is\ specified\ in\ 'Provisioning\ profile\ UUID',\ copy\ the\ specified\ file\ to\ a\ predetermined\ place.=\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u304C\u300C\u30D7\u30ED\u30D3\u30B8\u30E7\u30CB\u30F3\u30B0\u30D7\u30ED\u30D5\u30A1\u30A4\u30EBUUID\u300D\u306B\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3001\u6307\u5B9A\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u304C\u6240\u5B9A\u306E\u5834\u6240\u306B\u30B3\u30D4\u30FC\u3055\u308C\u307E\u3059\u3002 Use\ Legacy\ Build\ System?=\u65E7\u6765\u306E\u30D3\u30EB\u30C9\u30B7\u30B9\u30C6\u30E0\u3092\u4F7F\u7528\u3059\u308B Use\ the\ old\ 'Legacy\ Build\ System'\ instead\ of\ 'New\ Build\ System'\ of\ Xcode\ 9\ and\ later.=Xcode 9\u4EE5\u964D\u306E New Build System \u306E\u4EE3\u308F\u308A\u306B\u53E4\u3044 Legacy Build System \u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 Leave\ empty,\ it\ will\ not\ output\ a\ test\ result\ and\ will\ not\ analyze\ the\ test\ results.\ relative\ to\ the\ project-directory.=\u30C6\u30B9\u30C8\u7D50\u679C\u306E\u6982\u8981\u3092\u51FA\u529B\u3057\u306A\u3044\u5834\u5408\u306B\u306F\u7A7A\u306E\u307E\u307E\u306B\u3057\u307E\u3059\u3002\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u8D77\u70B9\u3068\u3057\u305F\u5225\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u30C6\u30B9\u30C8\u7D50\u679C\u306E\u6982\u8981\u3092\u51FA\u529B\u3057\u305F\u3044\u5834\u5408\u306B\u6307\u5B9A\u3057\u307E\u3059\u3002 Clean\ ResultBundlePath?=ResultBundlePath\u3092\u6D88\u53BB This\ will\ delete\ the\ ResultBundlePath\ before\ invoking\ the\ build.=\u30D3\u30EB\u30C9\u3092\u5B9F\u884C\u3059\u308B\u524D\u306BResultBundlePath\u3092\u6D88\u53BB\u3057\u307E\u3059 The\ 'Configure\ System'\ keychain\ information\ is\ used\ but\ this\ is\ a\ deprecated\ method.=\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u306E\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u60C5\u5831\u304C\u4F7F\u308F\u308C\u3066\u3044\u307E\u3059\u304C\u3001\u73FE\u5728\u306F\u3053\u308C\u306F\u975E\u63A8\u5968\u306E\u65B9\u6CD5\u3067\u3059\u3002 From\ now\ on,\ please\ move\ keychain\ information\ to\ 'Credentials'\ instead\ of\ 'Configure\ System'\ and\ use\ it.=\u4ECA\u5F8C\u306F\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u306E\u60C5\u5831\u306F\u300C\u30B7\u30B9\u30C6\u30E0\u306E\u8A2D\u5B9A\u300D\u3067\u306F\u306A\u304F\u300C\u8A8D\u8A3C\u60C5\u5831\u300D\u306B\u8A2D\u5B9A\u3057\u3066\u3001\u305D\u308C\u3092\u5229\u7528\u3059\u308B\u3088\u3046\u306B\u3057\u3066\u304F\u3060\u3055\u3044\u3002 The\ combination\ of\ path\ and\ password\ defined\ in\ 'Credentials'\ for\ unlocking\ the\ keychain\ used\ in\ this\ build.=\u3053\u306E\u30D3\u30EB\u30C9\u3067\u4F7F\u7528\u3059\u308B\u30AD\u30FC\u30C1\u30A7\u30FC\u30F3\u3092\u30A2\u30F3\u30ED\u30C3\u30AF\u3059\u308B\u305F\u3081\u306E\u300C\u8A8D\u8A3C\u60C5\u5831\u300D\u3067\u5B9A\u7FA9\u3055\u308C\u305F\u3001\u30D1\u30B9\u3068\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u7D44\u307F\u5408\u308F\u305B\u3002 ================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-allowFailingBuildResults.html ================================================

Checking this option will prevent a build step from failing if xcodebuild exits with a non-zero return code.
This can be useful for build steps that run unit tests and also have a post-build task to publish unit test results: the test step will not fail the entire build for a failing unit test, but will instead mark the build unstable in the "publish test" phase.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-allowFailingBuildResults_ja.html ================================================

このオプションをチェックすると、xcodebuildがゼロ以外のリターンコードで終了するとビルドステップが失敗するのを防ぐことができます。
    これはユニットテストを実行するビルドステップや、ユニットテスト結果を公開するビルド後のタスクを実行させるのに有用です。
テストステップでは失敗したユニットテストでビルド全体が失敗することはありませんが、代わりにテストを公開する段階で不安定となります。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-buildDir.html ================================================

The value to use for the BUILD_DIR setting. You only need to supply this value if you want the product of the Xcode build to be in a location other than the one specified in project settings and this job 'SYMROOT' parameter.
Supports all macros and also environment and build variables from the Token Macro Plugin.
For example you can use the value :

${WORKSPACE}/build
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-buildDir_ja.html ================================================

BUILD_DIRに使用する値を設定します。 Xcodeビルドの出力をプロジェクト設定で指定された場所や、このジョブの'SYMROOT'パラメータ以外の場所に変更する場合のみこの値を指定する必要があります。
ビルド変数に説明されている全ての環境変数とToken Macro Pluginで説明されている全てのマクロを使うことができます。
例えば次のような値を使用できます:

${WORKSPACE}/build
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-buildIpa.html ================================================

Checking this option will create a .ipa for each .app found in the build directory.
An .ipa is basically a zipped up .app.
This is quite handy for distributing ad-hoc builds to testers as they can just double-click the .ipa and it will import into iTunes.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-buildIpa_ja.html ================================================

このオプションを選択するとビルドディレクトリにある.appごとに.ipaが作成されます。
    .ipaは基本的に圧縮された.appです。
    これは.ipaをダブルクリックするだけでiTunesにインポートしたり、AdHocビルドをテスターに配布するのにとても便利です。

Checking this option will create a .ipa for each .app found in the build directory.
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-bundleID.html ================================================

The new bundle ID. Usually something like com.companyname.projectname.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-bundleIDInfoPlistPath.html ================================================

The path to the info.plist file which contains the CFBundleIdentifier of your project.
Usually something like:

  • ${WORKSPACE}/ProjectName/Project-Info.plist
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-bundleIDInfoPlistPath_ja.html ================================================

プロジェクトのCFBundleIdentifierを含むinfo.plistファイルへのパス。
通常は次の様な形式です:

  • ${WORKSPACE}/ProjectName/Project-Info.plist
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-bundleID_ja.html ================================================

新しいバンドルID。 通常はcom.companyname.projectnameのような形式です。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-cfBundleShortVersionStringValue.html ================================================

This will set the CFBundleShortVersionString to the specified string.
Supports all macros and also environment and build variables from the Token Macro Plugin.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-cfBundleShortVersionStringValue_ja.html ================================================

CFBundleShortVersionStringを指定された文字列に設定します。
ビルド変数で説明されている全ての環境変数とToken Macro Pluginで説明されている全てのマクロを使うことができます。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-cfBundleVersionValue.html ================================================

This will set the CFBundleVersion to the specified string.
Supports all macros and also environment and build variables from the Token Macro Plugin.
For example the value ${BUILD_NUMBER} will be replaced with the current build number.
We advice you to generate a unique value for each build if you want for example deploy it into a private store.
In that case, for example, you can use : ${JOB_NAME}-${BUILD_NUMBER}

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-cfBundleVersionValue_ja.html ================================================

CFBundleVersionを指定された文字列に設定します。
ビルド変数で説明されている全ての環境変数とToken Macro Pluginで説明されている全て>のマクロを使うことができます。
例えば ${BUILD_NUMBER} を指定すると、これは現在のビルド番号に置き換えられます。
例えばプライベートストアにアプリをデプロイする場合はなどには各ビルドで固有の値を生成する必要があるはずです。
このような場合には次の様にするとよいでしょう: ${JOB_NAME}-${BUILD_NUMBER}

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-changeBundleID.html ================================================

Checking this option will replace the bundle identifier.
You will need to specify which bundle ID (CFBundleIdentifier) to use and where is the Info.plist file located.
This is handy for example when you want to use a different code signing identity in your development projects.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-changeBundleID_ja.html ================================================

このオプションをチェックするとバンドルIDが置き換えられます。
バンドルID (CFBundleIdentifier) と使用するInfo.plist ファイルの場所を指定する必要があります。
これは、例えば開発段階では通常と異なるコード署名を行なう必要がある様な場合に便利です。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-cleanBeforeBuild.html ================================================

This will delete the build directories before invoking the build. This will force the rebuilding of ALL dependencies and can make large projects take a lot longer.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-cleanBeforeBuild_ja.html ================================================

ビルドを呼び出す前にビルドディレクトリが削除されます。 これにより全ての関連するものの再構築が強制され、大きなプロジェクトではとても時間かかることとなります。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-cleanResultBundlePath.html ================================================

This will delete the ResultBundlePath before invoking the build.
If the directory already exists in the location specified by ResultBundlePath, xcodebuild will be an error and should be checked.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-cleanResultBundlePath_ja.html ================================================

ビルドを呼び出す前にResultBundlePathが削除されます。
ResultBundlePathで指定された場所にすでにディレクトリが存在する場合、xcodebuildはエラーになるため、通常はチェックする必要があります。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-codeSigningIdentity.html ================================================

Override the code signing identity specified within the project config. This lets you keep your xcode project setup to build with developer certificates interactively but put your distribution certificate on the hosts running jenkins to build your actual releases.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-codeSigningIdentity_ja.html ================================================

プロジェクト設定内で指定されたコード署名IDを上書きします。 これによりデベロッパー証明書をインタラクティブ変更してビルドするようにxcodeプロジェクトの設定を行なうことができますが、リリースをビルドするためにjenkinsを実行するホストに航海用証明書を置いておく必要があります。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-configuration.html ================================================

This is the name of the configuration as defined in the Xcode project.
By default there are Debug and Release configurations.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-configuration_ja.html ================================================

これはXcodeプロジェクトで定義されているConfigurationの名前です。
デフォルトでは Debug と Release が定義されています。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-embeddedProfileFile.html ================================================

The relative path to the mobileprovision to embed, leave blank for no embedded profile.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-embeddedProfileFile_ja.html ================================================

埋め込み用の mobileprovision ファイルへの相対パスです。 埋め込み用のプロファイルが無いなら空欄のままにします。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-generateArchive.html ================================================

Checking this option will create an .xcarchive .app found in the build directory.
An .xcarchive is useful for submission to the app store or third party crash reporters.
You must specify a Scheme to perform an archive.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-generateArchive_ja.html ================================================

このオプションをチェックすると .xcarchive と .app をビルドディレクトリに作成します。
.xcarchive はApp Storeにアプリを送信したりサードパーティのクラッシュレポートを利用するのに便利です。
アーカイブの作成にはSchemeを指定する必要があります。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-globalDevelopmentTeam_ja.html ================================================

パッケージに署名するために利用する開発者チームの名前を指定します。 Xcode 8.3以降では.ipaに署名(これには現在xcodebuilderを使用しています)するために必要です。

開発者チームは開発者チームIDを指定するか、「Jenkinsの管理」で作成したものをここで設定できます

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-globalKeychainName_ja.html ================================================

パッケージに署名するための証明書を取得すのに使用する設定済みキーチェーンの名前。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-interpretTargetAsRegEx.html ================================================

Build all entries listed under the "Targets:" section of the xcodebuild -list output that match the regexp.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-interpretTargetAsRegEx_ja.html ================================================

xcodebuild -listの "Targets:" セクションにリストされているすべてのエントリから正規表現と一致するものをビルドします。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-ipaName_ja.html ================================================

出力するipaファイルのファイル名のパターンを指定します。
何も指定しなければアーカイブのベースネームにInfo.plistファイルの’CFBundleShortVersionString’の値と
’CFBundleVersion’の値を加えた文字列が使われます。
また、以下の表の値を文字列中に使用することができます。
${BASE_NAME}アーカイブのベースネームに置き換えられます
${VERSION}Info.plistのCFBundleVersionに置き換えられます
${SHORT_VERSION}Info.plistのCFBundleShortVersionStringに置き換えられます
${BUILD_DATE}アプリをビルドした日付(yyyy.MM.dd)に置き換えられます

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-keychainName.html ================================================

The name of this configured keychain. Each job will specify a keychain configuration by the name.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-keychainName_ja.html ================================================

設定済みのキーチェーンの名前。各ジョブでは名前で指定された設定済みのキーチェーンを利用します。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-keychainPath.html ================================================

The path of the keychain to use to retrieve certificates to sign the package (default : ${HOME}/Library/Keychains/login.keychain).

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-keychainPath_ja.html ================================================

パッケージに署名するための証明書を取得するキーチェーンのパス。 (デフィルトは: ${HOME}/Library/Keychains/login.keychain)

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-keychainPwd.html ================================================

The password of the keychain to use to retrieve certificates to sign the package.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-keychainPwd_ja.html ================================================

パッケージに署名するための証明書を取得するキーチェーンのパスワード。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-logfileOutputDirectory.html ================================================

Specify the directory to output the log of xcodebuild.
If you leave it blank, it will be output to "project directory/builds/${BUILD_NUMBER}/log" with other logs.
If an output path is specified, it is output as a xcodebuild.log file in a relative directory under the "build output directory"

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-logfileOutputDirectory_ja.html ================================================

xcodebuildのログを出力するディレクトリを指定します。
何も指定せずに空白のままにすると、他のログと共に "プロジェクトディレクトリ/builds/${BUILD_NUMBER}/log" へと出力されます。
出力パスを指定した場合には 「ビルドの出力ディレクトリ」 以下の相対ディレクトリに xcodebuild.log ファイルとして出力されます。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-resultBundlePath.html ================================================

Specify the directory to output the output the test result.
If you leave it blank, it will not output a test result and will not analyze the test results.
If an output path is specified, it is output as a test result in a relative directory under the "ResultBundlePath".
The plug-in analyzes the test result here and outputs a JUnit compatible XML file under the ${WORKSPACE}/test-reports.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-resultBundlePath_ja.html ================================================

テスト結果の概要を出力するディレクトリを指定します。
何も指定せずに空白のままにすると、テスト結果の概要は出力されず、またテスト結果の概要の解析も行われません。
出力パスを指定した場合にはプロジェクトルート以下に「ResultBundlePath」に指定された名前のディレクトリが作成され、そこにテスト結果の概要が出力されます。
そしてプラグインは出力されたテスト結果の概要を解析して、JUnit互換のXMLファイルを ${WORKSPACE}/test-reports 以下に出力します。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-sdk.html ================================================

You only need to supply this value if you want to specify the SDK to build against. If empty, the SDK will be determined by Xcode. If you wish to run OCUnit tests, you will need to use the iPhone Simulator's SDK, for example:

/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.1.sdk/
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-sdk_ja.html ================================================

ビルドで使用するSDKを指定する場合にのみこの値を指定する必要があります。 空の場合にはSDKはXcodeによって決定されます。OCUnitテストを実行する場合はiPhone SimulatorのSDKを使用する必要があります。 例:

/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.1.sdk/
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-signIpaOnXcrun.html ================================================

By default the xcode-plugin will sign the IPA when it runs xcrun on the app folder, dissabeling this will prevent xcrun from having the --sign option added to the command.
This fixes a known issue with Xcode on Mavericks:
http://stackoverflow.com/questions/32504355/error-itms-90339-this-bundle-is-invalid-the-info-plist-contains-an-invalid-ke http://stackoverflow.com/questions/32763288/ios-builds-ipa-creation-no-longer-works-from-the-command-line/32845990#32845990 http://cutting.io/posts/packaging-ios-apps-from-the-command-line/

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-signIpaOnXcrun_ja.html ================================================

By default the xcode-plugin will sign the IPA when it runs xcrun on the app folder, dissabeling this will prevent xcrun from having the --sign option added to the command.
This fixes a known issue with Xcode on Mavericks:
http://stackoverflow.com/questions/32504355/error-itms-90339-this-bundle-is-invalid-the-info-plist-contains-an-invalid-ke http://stackoverflow.com/questions/32763288/ios-builds-ipa-creation-no-longer-works-from-the-command-line/32845990#32845990 http://cutting.io/posts/packaging-ios-apps-from-the-command-line/

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-symRoot.html ================================================

You only need to supply this value if you want to specify the SYMROOT path to use.
If empty, the default SYMROOT path will be used (it could be different depending of your Xcode version).
Supports all macros and also environment and build variables from the Token Macro Plugin.
For example you can use the value :

${WORKSPACE}/symroot
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-symRoot_ja.html ================================================

SYMROOT として使うパスを指定する必要がある場合にだけ設定します。
空欄のままにすればデフォルトの SYMROOT パスが使われます。(これはXcodeのバージョンに依存します)
ビルド変数に説明されている全ての環境変数とToken Macro Pluginで説明されている>全てのマクロを使うことができます。
例えば次のような値を使用できます:

${WORKSPACE}/symroot
================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-target.html ================================================

The target to build. If left empty, this will build all targets in the project.
If you wish to build your binary and the unit test module, it is best to do this as two separate steps each with their own target.
This was, the iPhone Simulator SDK can be specified for the unit tests.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-target_ja.html ================================================

ビルドするターゲットです。空欄のままにするとプロジェクトの全てのターゲットをビルドします。
バイナリとユニットテストモジュールをビルドしたい場合には、それぞれ独自のターゲットを持つ2つの別々のステップとして実行するのが最善です。
そうすればiPhone Simulator SDKを単体テスト用に指定することができます。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-unlockKeychain_ja.html ================================================

アーカイブに署名を行なう前にキーチェーンのロックを自動的に解除します。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-useLegacyBuildSystem.html ================================================

Instead of "New Builld System" which became available from Xcode 9, we build the application using the legacy build system.
There is a possibility that you can handle old projects that cause problems with the new build system.
Also, since new output formats of logs are changed in the new build system, it is also useful when you want to handle logs with legacy third party tools.

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-useLegacyBuildSystem_ja.html ================================================

Xcode 9から利用可能となった"New Builld System"ではなく、旧来のビルドシステムを使ってアプリケーションのビルドを行います。
それによって新しいビルドシステムでは問題が起きる古いプロジェクトを扱う事ができる可能性があります。
また、新しいビルドシステムではログの出力フォーマットなどにも変更があるため、ログを旧来のサードパーティ製ツールで扱いたい場合にも便利です。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-xcodeProjectFile_ja.html ================================================

もし、1つ以上のXcodeプロジェクトファイルがプロジェクトのパスに存在しているならば、どのプロジェクトをビルドの対象とするかを指定する必要があります。
もし、全てのプロジェクトをビルドする必要があるならば、それぞれのXcodeプロジェクトごとにXcodeのビルド手順を作成する必要があります。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-xcodeProjectPath_ja.html ================================================

ワークスペース(workspace)からの相対パスでXcodeプロジェクトファイルが置かれたディレクトリの場所を指定します。 これはワークスペーストップディレクトリにXcodeプロジェクトのディレクトリが置かれていない場合ののみ指定が必要です。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-xcodeSchema_ja.html ================================================

もし、あなたが「ターゲット」の設定よりも schema を優先してコンパイルしたい場合や、アーカイブや.ipaを生成したい場合に指定します。 この設定はXcodeのプロジェクトファイルでの設定やこのジョブの「ターゲット」での設定よりも優先されます。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-xcodeWorkspaceFile_ja.html ================================================

もし、あなたがprojectではなくworkspaceを使ってコンパイルを行ないたいなら指定します。 この設定はXcodeのプロジェクトファイルでの設定やこのジョブの「Configuration」パラメータよりも優先されます。

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-xcodebuildArguments.html ================================================

Extra xcodebuild parameters, added after the command that jenkins generates based on the rest of the config

================================================ FILE: src/main/resources/au/com/rayh/XCodeBuilder/help-xcodebuildArguments_ja.html ================================================

その他の設定に基づいてJenkinsが生成するコマンドの後に追加するxcodebuildパラメータ

================================================ FILE: src/main/resources/hudson/plugins/xcode/XcodeInstallation/config.jelly ================================================ ================================================ FILE: src/main/resources/hudson/plugins/xcode/XcodeInstallation/config_it.properties ================================================ Name=Nome Path\ to\ Xcode\ tools=Percorso del file eseguibile Xcode utensili ================================================ FILE: src/main/resources/hudson/plugins/xcode/XcodeInstallation/config_ja.properties ================================================ # The MIT License # # Copyright (c) 2016-, Seiji Sogabe # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. Name=\u540d\u524d Path\ to\ Xcode\ tools=Xcode tools\u3078\u306e\u30d1\u30b9 ================================================ FILE: src/main/resources/hudson/plugins/xcode/XcodeInstallation/help-home.html ================================================
Set path to Xcode tools. This is the path displayed when executing "xcode-select -p".
================================================ FILE: src/main/resources/hudson/plugins/xcode/XcodeInstallation/help-home_ja.html ================================================
Xcode toolsへのパスを指定します。これは"xcode-select -p"を実行した時に表示されるパスです。
================================================ FILE: src/main/resources/index.jelly ================================================
This plugin provides builders to build xcode projects, invoke agvtool and package .ipa files
================================================ FILE: src/main/webapp/help/help-appIDandProvisionUUID.html ================================================

Set the application's Buldle ID and UUID or identifier combination of the provisioning profile to use when signing the application.
The Buldle ID specified here and the UUID or identifier combination of the provisioning profile are recorded in the exportOptions.plist file and used for CodeSign when exporting IPA from the archive.

================================================ FILE: src/main/webapp/help/help-appIDandProvisionUUID_ja.html ================================================

アプリケーションに署名する際に使用する、アプリの Buldle IDとプロビジョニングプロファイルのUUIDまたは識別子の組み合わせを設定します。
ここで指定されたBuldle IDとプロビジョニングプロファイルのUUIDまたは識別子の組み合わせはexportOptions.plistファイルへと記録され、アーカイブからIPAをエキスポートする際にCodeSignで使われます。

================================================ FILE: src/main/webapp/help/help-assetPackManifestURL.html ================================================

Export settings for non-App Store App.
If the application is using on-demand resources and the application will installing OTA with manifest.plist, this must be the base URL that specifies the host of the asset pack. This will set up the app to download the asset pack from the specified URL.

================================================ FILE: src/main/webapp/help/help-assetPackManifestURL_ja.html ================================================

非App Store向けエクスポートの設定です。
アプリがオンデマンドリソースを使用していてアプリケーションがmanifest.plistを使用してOTAでインストールされる場合、これはアセットパックのホスト先を指定するベースURLでなければなりません。 これにより、指定されたURLからアセットパックをダウンロードするようにアプリが設定されます。

================================================ FILE: src/main/webapp/help/help-automaticSigning.html ================================================

Checking this option will automatically generate Provisioning Profile and certificates for signing application.
However, please be aware that using this function will automatically create Provisioning profile and certificates as necessary, so that old Provisioning profile and certificates will be invalid at that time.

================================================ FILE: src/main/webapp/help/help-automaticSigning_ja.html ================================================

このオプションをオンにするとプロビジョニングプロファイルとアプリケーション署名用の証明書が自動的に生成されます。
ただし、この機能を使用すると、必要に応じてプロビジョニングプロファイルと証明書が自動的に作成されるため、その時点で古いプロビジョニングプロファイルと証明書は無効になることに注意が必要です。

================================================ FILE: src/main/webapp/help/help-bundleID.html ================================================

Specify the Bundle ID of the application for which code sign to be performed.
If the location of the Info.plist file contained in the compiled archive is set instead of the Bundle ID, read the Bundle ID from the Info.plist file and use that value.

================================================ FILE: src/main/webapp/help/help-bundleID_ja.html ================================================

コード署名を行なう対象となるアプリケーションのBundle IDを指定します。
Bundle IDの代わりにコンパイル済みのアーカイブに含まれているInfo.plistファイルの場所が設定された場合には、Info.plistファイルからBundle IDを読み取り、その値を使用します。

================================================ FILE: src/main/webapp/help/help-compileBitcode.html ================================================

If checked, Xcode will recompiling Bitcode and exporting IPA for the non App Store.
The default is "Yes" (check is on).

================================================ FILE: src/main/webapp/help/help-compileBitcode_ja.html ================================================

App Store向け以外のIPAをBitcodeをリコンパイルしてエクスポートするならチェックします。
デフォルトは「はい」(チェックはオン)です。

================================================ FILE: src/main/webapp/help/help-copyProvisioningProfile.html ================================================

If Checked, If Checked, and the filename of provisioning profile is specified in "Provisioning profile UUID", the specified file is copied to a predetermined place.
("/Users/${HOME}/Library/MobileDevice/Provisioning Profiles/")
This can be used to overwrite the contents of the developer profile or system settings in the provisioning profile in the project deployed from SCM etc.
If the provisioning profile UUID or Specifire is set in "provisioning profile UUID", it does not do anything. The default is "Yes" (check is on).

================================================ FILE: src/main/webapp/help/help-copyProvisioningProfile_ja.html ================================================

チェックされ、「プロビジョニングプロファイルUUID」にプロビジョニングプロファイルのファイル名が設定されている場合は、
指定されたファイルを所定の場所にコピーします。
("/Users/${HOME}/Library/MobileDevice/Provisioning Profiles/")
これはSCMなどから展開されたプロジェクト中のプロビジョニングプロファイルで開発者プロファイルの内容やシステム設定を上書きするのに使えます。
「プロビジョニングプロファイルUUID」に設定されているのがプロビジョニングプロファイルのUUIDや識別子なら何もしません。
デフォルトは「はい」(チェックはオン)です。

================================================ FILE: src/main/webapp/help/help-credentialKeychainId.html ================================================

The combination of the path and password defined in 'Credentials' for unlocking the keychain that contains the certificate for signing the package.

================================================ FILE: src/main/webapp/help/help-credentialKeychainId_ja.html ================================================

パッケージに署名するための証明書を格納したキーチェーンをアンロックするための「認証情報」で定義されたパスとパスワードの組み合わせ。

================================================ FILE: src/main/webapp/help/help-developmentTeamID.html ================================================

The ID of the configured development team to use to sign the package. As of XCode 8.3, this is required now to sign an ipa (which now uses xcodebuilder).

If you want to use Xcode default for developer team ID, leave this field blank.

================================================ FILE: src/main/webapp/help/help-developmentTeamID_ja.html ================================================

パッケージに署名するために利用する開発者チームIDを指定します。 Xcode 8.3以降では.ipaに署名(これには現在xcodebuilderを使用しています)するために必要です。

開発者チームIDにXcodeのデフォルトを使用する場合はこのフィールドを空白のままにします。

================================================ FILE: src/main/webapp/help/help-displayImageURL.html ================================================

Export settings for non App Store.
Specify the URL of the image (57 x 57 pixels) of the icon to be displayed when installing the application using manifest.plist.

================================================ FILE: src/main/webapp/help/help-displayImageURL_ja.html ================================================

非App Store向けエクスポートの設定です。
manifest.plistを使ってアプリケーションをインストールする際に表示するアイコ ンの画像(57x57ピクセル)のURLを指定します。

================================================ FILE: src/main/webapp/help/help-embedOnDemandResources.html ================================================

Export settings for non App Store.
If the application is using on demand resources and this item is on, the asset pack is included in the application bundle, so you can test the app without the server hosting the asset pack.
If onDemandResourcesAssetPacksBaseURL is not specified, the default is YES (check is on).

================================================ FILE: src/main/webapp/help/help-embedOnDemandResources_ja.html ================================================

非App Store向けエクスポートの設定です。
アプリケーションがオンデマンドリソースを使用していている場合、かつこの項目がオンなら、アセットパックはアプリケーションバンドルに組み込まれるため、アセットパックをホストするサーバーなしでアプリをテストできます。
onDemandResourcesAssetPacksBaseURLが指定されていない場合、デフォルトは「はい」(チェックはオン)です。

================================================ FILE: src/main/webapp/help/help-fullSizeImageURL.html ================================================

Export settings for non App Store.
Specify the URL of the image (512 x 512 pixels) of the icon to be displayed when installing the application using manifest.plist.

================================================ FILE: src/main/webapp/help/help-fullSizeImageURL_ja.html ================================================

非App Store向けエクスポートの設定です。
manifest.plistを使ってアプリケーションをインストールする際に表示するアイコンの画像(512x512ピクセル)のURLを指定します。

================================================ FILE: src/main/webapp/help/help-globalDevelopmentTeam.html ================================================

The name of the configured development team to use to sign the package. As of XCode 8.3, this is required now to sign an ipa (which now uses xcodebuilder).

A development team can be configured here by specifying a Development Team ID, or by creating one in the jenkins global configuration

================================================ FILE: src/main/webapp/help/help-globalDevelopmentTeam_ja.html ================================================

パッケージに署名するために利用する開発者チームの名前を指定します。 Xcode 8.3以降では.ipaに署名(これには現在xcodebuilderを使用しています)するために必要です。

開発者チームは開発者チームIDを指定するか、「Jenkinsの管理」で作成したものをここで設定できます

================================================ FILE: src/main/webapp/help/help-globalKeychainName.html ================================================

The name of the configured keychain to use to retrieve certificates to sign the package.

================================================ FILE: src/main/webapp/help/help-globalKeychainName_ja.html ================================================

パッケージに署名するための証明書を取得すのに使用する設定済みキーチェーンの名前。

================================================ FILE: src/main/webapp/help/help-importDeveloperProfile.html ================================================

Select the developer profile you exported from Xcode Preference to import into the keychain. Developer profile must be registered with Jenkins in advance by "Credentials". If you do not select this column, you can specify the identifier of the developer profile registered in "Credentials" with the next "Developer Profile ID".

================================================ FILE: src/main/webapp/help/help-importDeveloperProfileId.html ================================================

Specify the developer profile id you exported from Xcode Preference to import into the keychain. Developer profile must be registered with Jenkins in advance by "Credentials".

================================================ FILE: src/main/webapp/help/help-importDeveloperProfileId_ja.html ================================================

キーチェーンにインポートする、XcodeのPreferenceからエクスポートした開発者プロファイルのIDを設定します。 開発者プロファイルは事前に「認証情報」でJenkinsへと登録されている必要があります。

================================================ FILE: src/main/webapp/help/help-importDeveloperProfile_ja.html ================================================

キーチェーンにインポートする、XcodeのPreferenceからエクスポートした開発者プロファイルを選択します。 開発者プロファイルは事前に「認証情報」でJenkinsへと登録されている必要があります。 この欄を選択しない場合には、次の「開発者プロファイルのID」で「認証情報」に登録されている開発者プロファイルの識別子(ID)を指定する事ができます。

================================================ FILE: src/main/webapp/help/help-importIntoExistingKeychain.html ================================================

If it is checked, the developer profile will be imported into the existing keychain. If not checked, create a new key chain with the file name "jenkins-" + "job name" newly, and import the developer profile into this. (In this case, a random character string is automatically generated and used for the password) When importing developer profiles into a temporary key chain, please make sure that there are no duplicate certificates or private keys in the developer profile you import into the default keychain etc. If duplicate certificates or secret keys are included in both, Xcode gets confused and can not process the codesign correctly.

================================================ FILE: src/main/webapp/help/help-importIntoExistingKeychain_ja.html ================================================

チェックされている場合には、開発者プロファイルは既存のキーチェーンへとインポートされます。 チェックされていないなら、新しく"jenkins-" + "ジョブ名”のファイル名でキーチェーンを新しく作成して、これに開発者プロファイルをインポートします。(この場合には、パスワードには自動的にランダムな文字列が生成されて使われます) 開発者プロファイルを新規のキーチェーンにインポートする際は、デフォルトのキーチェーンなどにインポートするデベロッパープロファイルと重複した証明書や秘密鍵がないことを確認してください。 重複した証明書や秘密鍵が複数のキーチェーンに含まれていると、Xcodeが混乱してしまいコード署名を正しく処理できません。

================================================ FILE: src/main/webapp/help/help-importKeychainId.html ================================================

The ID of a keychain defined in 'Credentials' to import a certificate for signing a package from a developer profile.

================================================ FILE: src/main/webapp/help/help-importKeychainId_ja.html ================================================

パッケージに署名するための証明書を開発者プロファイルからインポートする、「認証情報」で定義済みのキーチェーンID。

================================================ FILE: src/main/webapp/help/help-importKeychainName.html ================================================

The name of the configured keychain to use to import certificates from developer profile to sign the package.

================================================ FILE: src/main/webapp/help/help-importKeychainName_ja.html ================================================

パッケージに署名するための証明書を開発者プロファイルからインポートする設定済みキーチェーンの名前。

================================================ FILE: src/main/webapp/help/help-ipaExportMethod.html ================================================

The export method of the .app to generate the .ipa file. Should be one in 'development', 'ad-hoc', 'enterprise' or 'app-store'.

================================================ FILE: src/main/webapp/help/help-ipaExportMethod_ja.html ================================================

.appから.ipaを生成する際のエクスポート方法をdevelopment、ad-hoc、enterprise、app-storeのいずれかで指定します。

================================================ FILE: src/main/webapp/help/help-ipaManifestPlistUrl.html ================================================

Export settings for non App Store.
The user can open the distribution manifest file with a Web browser and download the application on the Web.
Set the URL for downloading the application here.

================================================ FILE: src/main/webapp/help/help-ipaManifestPlistUrl_ja.html ================================================

非App Store向けエクスポートの設定です。
ユーザーは、Webブラウザで配布マニフェストファイルを開いて、Web上でアプリをダウンロードできます。
アプリケーションをダウンロードするためのURLをここに設定します。

================================================ FILE: src/main/webapp/help/help-ipaName.html ================================================

Specify the file name pattern of the ipa file to be output.
If nothing is specified, the base name of the archive plus the value of 'CFBundleShortVersionString'
plus the value of 'CFBundleVersion' in the Info.plist file is used.
In addition, the values in the following table can be used in the string.< br/>
${BASE_NAME}It is replaced with the base name of the archive
${VERSION}It is replaced with CFBundleVersion in Info.plist
${SHORT_VERSION}It is replaced with CFBundleShortVersionString in Info.plist
${BUILD_DATE}It is replaced with date on which the application was built (yyyy.MM.dd)

================================================ FILE: src/main/webapp/help/help-ipaName_ja.html ================================================

出力するipaファイルのファイル名のパターンを指定します。
何も指定しなければアーカイブのベースネームにInfo.plistファイルの’CFBundleShortVersionString’の値と
’CFBundleVersion’の値を加えた文字列が使われます。
また、以下の表の値を文字列中に使用することができます。
${BASE_NAME}アーカイブのベースネームに置き換えられます
${VERSION}Info.plistのCFBundleVersionに置き換えられます
${SHORT_VERSION}Info.plistのCFBundleShortVersionStringに置き換えられます
${BUILD_DATE}アプリをビルドした日付(yyyy.MM.dd)に置き換えられます

================================================ FILE: src/main/webapp/help/help-ipaOutputDirectory.html ================================================

The output directory for the .ipa file, relative to the build directory.

================================================ FILE: src/main/webapp/help/help-ipaOutputDirectory_ja.html ================================================

.ipaファイルの出力ディレクトリをビルド作業用ディレクトリ(build)からの相対パスで指定します。

================================================ FILE: src/main/webapp/help/help-manifestPlistURL.html ================================================

Specify the URL for installing the application when creating the manifest.plist that is necessary when OTA installing the application from Web pages or email.

================================================ FILE: src/main/webapp/help/help-manifestPlistURL_ja.html ================================================

WebサートやメールからアプリケーションをOTAインストールする際に必要なmanifest.plistを作成する場合にアプリケーションをインストールするためのURLを指定します。

================================================ FILE: src/main/webapp/help/help-manualSigning.html ================================================

For this option you need to manually specify the combination of Provisioning profile UUID and BundleID.
This will be useful if you want to change the combination of Provisioning Profile and Certificate used for CodeSign when you build the application.

================================================ FILE: src/main/webapp/help/help-manualSigning_ja.html ================================================

このオプションではプロビジョニングプロファイルのUUIDとBundleIDの組み合わせを手動で指定する必要があります。
これは、アプリケーションをビルドするときにコード署名で使用されるプロビジョニングプロファイルと証明書の組み合わせを変更したい場合に便利です。

================================================ FILE: src/main/webapp/help/help-onDemandResourcesURL.html ================================================

Export settings for non-App Store.
If the application is using an on demand resource and embedOnDemandResourcesAssetPacksInBundle is not YES, this must be the base URL that specifies the host of the asset pack. This will set up the app to download the asset pack from the specified URL.

================================================ FILE: src/main/webapp/help/help-onDemandResourcesURL_ja.html ================================================

非App Store向けエクスポートの設定です。
アプリがオンデマンドリソースを使用していてembedOnDemandResourcesAssetPacksInBundleがYESでない場合、これはアセットパックのホスト先を指定するベースURLでなければなりません。 これにより、指定されたURLからアセットパックをダウンロードするようにアプリが設定されます。

================================================ FILE: src/main/webapp/help/help-provisioningUUID.html ================================================

Specify the UUID or Specifire of the provisioning profile to use to sign the application. If the location of the provisioning profile is set instead of the UUID or Specifire, read the UUID from the provisioning profile and use that value.

================================================ FILE: src/main/webapp/help/help-provisioningUUID_ja.html ================================================

アプリケーションに署名するのに使用するプロビジョニングプロファイルのUUIDまたは識別子を指定します。
UUIDまたは識別子の代わりにプロビジョニングプロファイルの場所が設定された場合には、プロビジョニングプロファイルからUUIDを読み取り、その値を使用します。

================================================ FILE: src/main/webapp/help/help-readFromProject.html ================================================

With this option, it automatically retrieve and sets the combination of BundleID and Provisioning profile UUID from the Xcode project file.
This is useful when you want to take over the combination of BundleID and Provisioning profile UUID that you used in the Xcode project (GUI).
"Read from Xcode Project" requires the following "Build Configuration" corresponding to "Export method" of "General build settings".
Export methodBuild Configuration
developmentDebug
ad-hocAdHoc
enterpriseEnterprise
app-storeRelease

================================================ FILE: src/main/webapp/help/help-readFromProject_ja.html ================================================

このオプションを使用するとBundleIDとプロビジョニングプロファイルUUIDの組み合わせがXcodeプロジェクトファイルから自動的に取得され設定されます。
これは、Xcodeプロジェクト(GUI)で使用したBundleIDとプロビジョニングプロファイルUUIDの組み合わせを引き継ぐ場合に便利です。
「Xcodeプロジェクトから読み込む」を使うには「全体のビルド設定」の「エクスポート方法」に対応する以下の「ビルド構成」が必要です。
エクスポート方法ビルド構成
developmentDebug
ad-hocAdHoc
enterpriseEnterprise
app-storeRelease

================================================ FILE: src/main/webapp/help/help-thinning.html ================================================

Set this to thin the packages for one or more devices in Xcode when exporting IPA by methods other than App Store.

Available options are:
<none> (Xcode export non-thinned generic application),
<thin-for-all-variants> (Xcode export universal applications and all available thinning variants),
Or for a model identifier a specific device (eg "iPhone 7, 1").
The default is <none>.

================================================ FILE: src/main/webapp/help/help-thinning_ja.html ================================================

App Store向け以外の方法でIPAをエクスポートする場合にXcodeで1つ以上のデバイス向けにパッケージを最適化したい場合に設定します。

利用可能なオプションは:
<none> (Xcodeは最適化されていない汎用アプリケーションを生成する),
<thin-for-all-variants> (Xcodeは汎用アプリケーション向けに可能な限りの最適化を行ないIPAを生成する),
または特定のデバイスのモデル識別子 (例えば "iPhone 7, 1") 向けに最適化する。
デフォルトは <none> です。

================================================ FILE: src/main/webapp/help/help-unlockKeychain.html ================================================

Automatically unlock the keychain before signing the archive?

================================================ FILE: src/main/webapp/help/help-unlockKeychain_ja.html ================================================

アーカイブに署名を行なう前にキーチェーンのロックを自動的に解除します。

================================================ FILE: src/main/webapp/help/help-uploadBitcode.html ================================================

If Checked, include bitcode in IPA exporting for App Store.
The default is "Yes" (check is on).

================================================ FILE: src/main/webapp/help/help-uploadBitcode_ja.html ================================================

App Store向けにエクスポートするIPAにBitcodeを含める場合にはチェックします。
デフォルトは「はい」(チェックはオン)です。

================================================ FILE: src/main/webapp/help/help-uploadSymbols.html ================================================

If Checked, include symbols in IPA exporting for App Store.
The default is "Yes" (check is on).

================================================ FILE: src/main/webapp/help/help-uploadSymbols_ja.html ================================================

App Store向けにエクスポートするIPAにシンボルを含める場合にはチェックします。
デフォルトは「はい」(チェックはオン)です。

================================================ FILE: src/main/webapp/help/help-xcodeProjectFile.html ================================================

If there is more than one Xcode project file in the project path, you will need to specify the file name of the project you wish to build.
If you need to build all project, you will need to create an Xcode build step for each one manually.

================================================ FILE: src/main/webapp/help/help-xcodeProjectFile_ja.html ================================================

もし、1つ以上のXcodeプロジェクトファイルがプロジェクトのパスに存在しているならば、どのプロジェクトをビルドの対象とするかを指定する必要があります。
もし、全てのプロジェクトをビルドする必要があるならば、それぞれのXcodeプロジェクトごとにXcodeのビルド手順を作成する必要があります。

================================================ FILE: src/main/webapp/help/help-xcodeProjectPath.html ================================================

This is the relative path from the workspace to the directory that contains the Xcode project file. You only need to supply this value if the Xcode project you wish to build is not in the root of the workspace.

================================================ FILE: src/main/webapp/help/help-xcodeProjectPath_ja.html ================================================

ワークスペース(workspace)からの相対パスでXcodeプロジェクトファイルが置かれたディレクトリの場所を指定します。 これはワークスペーストップディレクトリにXcodeプロジェクトのディレクトリが置かれていない場合ののみ指定が必要です。

================================================ FILE: src/main/webapp/help/help-xcodeSchema.html ================================================

Needed if you want to compile for a specific schema instead of a target, or if you want to generate an archive or an IPA. It takes precedence over 'Xcode Configuration' setting and this job 'target' parameter.

================================================ FILE: src/main/webapp/help/help-xcodeSchema_ja.html ================================================

もし、あなたが「ターゲット」の設定よりも schema を優先してコンパイルしたい場合や、アーカイブや.ipaを生成したい場合に指定します。 この設定はXcodeのプロジェクトファイルでの設定やこのジョブの「ターゲット」での設定よりも優先されます。

================================================ FILE: src/main/webapp/help/help-xcodeToolsVersion.html ================================================

Select the version of Xcode Tools to use for building the project.

You can select the version of Xcode set by 'Global Tool Configuration' by plugin setting.
If you choose the 'System Default' for Xcode version, plugin will not do anything, so you can switch Xcode using environment variable 'DEVELOPER_DIR' as well.

================================================ FILE: src/main/webapp/help/help-xcodeToolsVersion_ja.html ================================================

プロジェクトのビルドに使用するXcodeツールのバージョンを選択します。

プラグイン設定で「Global Tool Configuration」で設定したXcodeのバージョンを選択できます。
Xcode toolsのバージョンに「システムの設定」を選択した場合、プラグインは何もしませんが、 その場合には今までどおり環境変数 'DEVELOPER_DIR' を使ってXcodeを切り替えることもできます。

================================================ FILE: src/main/webapp/help/help-xcodeWorkspaceFile.html ================================================

Only needed if you want to compile a workspace instead of a project. It takes precedence over 'Xcode Project File' setting and this job 'configuration' parameter."

================================================ FILE: src/main/webapp/help/help-xcodeWorkspaceFile_ja.html ================================================

もし、あなたがprojectではなくworkspaceを使ってコンパイルを行ないたいなら指定します。 この設定はXcodeのプロジェクトファイルでの設定やこのジョブの「Configuration」パラメータよりも優先されます。

================================================ FILE: src/main/webapp/help-cleanTestReports.html ================================================

This will delete the processed test reports before invoking the build. Usually it is a good idea only to do it in test targets, otherwise if other Xcode target is built before tests – the build will fail to collect test reports.

================================================ FILE: src/main/webapp/help-xcodebuildArguments.html ================================================

Arguments are currently separated by space, enclosing them in quotes won't help.

Passing custom arguments is convenient when you need to change some project options for Jenkins build, but don't want them to persist in project file. For example when running application tests, following settings often are nice fit: GCC_SYMBOLS_PRIVATE_EXTERN=NO COPY_PHASE_STRIP=NO. Otherwise Release build will usually fail because it won't be able to find application symbols to link with test bundle.

================================================ FILE: src/test/java/Pkcs12.java ================================================ import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import javax.security.auth.x500.X500Principal; import java.io.FileInputStream; import java.security.KeyStore; import java.security.cert.X509Certificate; import java.util.Enumeration; /** * A test program to inspect PKCS12 file * * @author Kohsuke Kawaguchi */ public class Pkcs12 { public static void main(String[] args) throws Exception { KeyStore ks = KeyStore.getInstance("pkcs12"); ks.load(new FileInputStream(args[0]),args[1].toCharArray()); Enumeration en = ks.aliases(); while (en.hasMoreElements()) { String s = en.nextElement(); System.out.println(s); X509Certificate c = (X509Certificate)ks.getCertificate(s); if (c!=null) { X500Principal p = c.getSubjectX500Principal(); System.out.println(p.getName()); System.out.println(getCanonicalName(p)); } } } private static String getCanonicalName(X500Principal p) throws InvalidNameException { LdapName n = new LdapName(p.getName()); for (Rdn rdn : n.getRdns()) { if (rdn.getType().equalsIgnoreCase("CN")) return rdn.getValue().toString(); } return p.getName(); // fallback } } ================================================ FILE: src/test/java/Pkcs7.java ================================================ import hudson.util.IOUtils; import org.bouncycastle.cms.CMSSignedData; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; /** * @author Kohsuke Kawaguchi */ public class Pkcs7 { public static void main(String[] args) throws Exception { CMSSignedData cms = new CMSSignedData(IOUtils.toByteArray(new FileInputStream(args[0]))); ByteArrayOutputStream payload = new ByteArrayOutputStream(); cms.getSignedContent().write(payload); // mobile provisioning profile has a payload of plist System.out.write(payload.toByteArray()); } } ================================================ FILE: src/test/java/au/com/rayh/JenkinsXCodeBuildOutputParserTest.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package au.com.rayh; import hudson.FilePath; import hudson.console.ConsoleNote; import hudson.model.TaskListener; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * * @author ray */ public class JenkinsXCodeBuildOutputParserTest { OutputParserTests test; @Before public void setUp() throws IOException, InterruptedException { JenkinsXCodeBuildOutputParser parser = new JenkinsXCodeBuildOutputParser(new FilePath(new File(".")), new TaskListener() { public PrintStream getLogger() { try { return new PrintStream("test-output.txt"); } catch(FileNotFoundException e) { throw new RuntimeException(e); } } public void annotate(ConsoleNote consoleNote) throws IOException { throw new UnsupportedOperationException("Not supported yet."); } public void hyperlink(String s, String s1) throws IOException { throw new UnsupportedOperationException("Not supported yet."); } public PrintWriter error(String string) { throw new UnsupportedOperationException("Not supported yet."); } public PrintWriter error(String string, Object... os) { throw new UnsupportedOperationException("Not supported yet."); } public PrintWriter fatalError(String string) { throw new UnsupportedOperationException("Not supported yet."); } public PrintWriter fatalError(String string, Object... os) { throw new UnsupportedOperationException("Not supported yet."); } }); test = new OutputParserTests(parser); } @After public void tearDown() { } @Test public void shouldIgnoreStartSuiteLineThatContainsFullPath() throws Exception { test.shouldIgnoreStartSuiteLineThatContainsFullPath(); } @Test public void shouldParseStartTestSuite() throws Exception { test.shouldParseStartTestSuite(); } @Test public void shouldParseEndTestSuite() throws Exception { test.shouldParseEndTestSuite(); } @Test public void shouldParseStartTestCase() throws Exception { test.shouldParseStartTestCase(); } @Test public void shouldAddErrorToTestCase() throws Exception { test.shouldAddErrorToTestCase(); } @Test public void shouldParsePassedTestCase() throws Exception { test.shouldParsePassedTestCase(); } @Test public void shouldParseFailedTestCase() throws Exception { test.shouldParseFailedTestCase(); } } ================================================ FILE: src/test/java/au/com/rayh/OutputParserTests.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package au.com.rayh; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.util.Date; import au.com.rayh.report.TestCase; import au.com.rayh.report.TestSuite; /** * * @author ray */ class OutputParserTests { XCodeBuildOutputParser parser; OutputParserTests(XCodeBuildOutputParser theParser) { parser = theParser; } void shouldIgnoreStartSuiteLineThatContainsFullPath() throws Exception { String line = "Test Suite '/Users/ray/Development/Projects/Java/xcodebuild-hudson-plugin/work/jobs/PBS Streamer/workspace/build/Debug-iphonesimulator/TestSuite.octest(Tests)' started at 2010-10-02 13:39:22 GMT 0000"; parser.handleLine(line); assertNull(parser.currentTestSuite); } void shouldParseStartTestSuite() throws Exception { String line = "Test Suite 'PisClientTestCase' started at 2010-10-02 13:39:23 GMT 0000"; parser.handleLine(line); assertNotNull(parser.currentTestSuite); assertEquals("PisClientTestCase", parser.currentTestSuite.getName()); assertEquals(new Date(Date.UTC(110, 9, 2, 13, 39, 23)), parser.currentTestSuite.getStartTime()); } void shouldParseEndTestSuite() throws Exception { parser.currentTestSuite = new TestSuite("host", "PisClientTestCase", new Date()); parser.testSuitesHash.put("PisClientTestCase", parser.currentTestSuite); String line = "Test Suite 'PisClientTestCase' finished at 2010-10-02 13:41:23 GMT 0000."; parser.handleLine(line); assertNull(parser.currentTestSuite); assertEquals(0, parser.exitCode); } void shouldParseStartTestSuiteXC() throws Exception { String line = "Test Suite 'All tests' started at 2014-12-12 05:12:52 +0000"; parser.handleLine(line); assertNotNull(parser.currentTestSuite); assertEquals("All tests", parser.currentTestSuite.getName()); assertEquals(new Date(Date.UTC(114, 11, 12, 05, 12, 52)), parser.currentTestSuite.getStartTime()); } void shouldParseEndTestSuiteXC() throws Exception { parser.currentTestSuite = new TestSuite("host", "All tests", new Date()); parser.testSuitesHash.put("All tests", parser.currentTestSuite); String line = "Test Suite 'All tests' passed at 2014-12-12 05:12:52 +0000."; parser.handleLine(line); assertNull(parser.currentTestSuite); assertEquals(0, parser.exitCode); } void shouldParseStartTestCase() throws Exception { parser.currentTestSuite = new TestSuite("host", "PisClientTestCase", new Date()); parser.testSuitesHash.put("PisClientTestCase", parser.currentTestSuite); String line = "Test Case '-[PisClientTestCase testThatFails]' started."; parser.handleLine(line); assertNotNull(parser.currentTestCase); assertEquals("testThatFails", parser.currentTestCase.getName()); } void shouldAddErrorToTestCase() throws Exception { parser.currentTestSuite = new TestSuite("host", "PisClientTestCase", new Date()); parser.testSuitesHash.put("PisClientTestCase", parser.currentTestSuite); parser.currentTestCase = new TestCase("PisClientTestCase", "testThatFails"); parser.currentTestSuite.getTestCasesHash().put("testThatFails", parser.currentTestCase); String line = "/Users/ray/Development/Projects/Java/xcodebuild-hudson-plugin/work/jobs/PBS Streamer/workspace/PisClientTestCase.m:21: error: -[PisClientTestCase testThatFails] : \"((nil) != nil)\" should be true. This always fails"; parser.handleLine(line); assertEquals(1, parser.currentTestCase.getFailures().size()); assertEquals("/Users/ray/Development/Projects/Java/xcodebuild-hudson-plugin/work/jobs/PBS Streamer/workspace/PisClientTestCase.m:21", parser.currentTestCase.getFailures().get(0).getLocation()); assertEquals("\"((nil) != nil)\" should be true. This always fails", parser.currentTestCase.getFailures().get(0).getMessage()); } void shouldAddUIErrorToTestCase() throws Exception { parser.currentTestSuite = new TestSuite("host", "PisClientTestCase", new Date()); parser.testSuitesHash.put("PisClientTestCase", parser.currentTestSuite); parser.currentTestCase = new TestCase("PisClientTestCase", "testThatFails"); parser.currentTestSuite.getTestCasesHash().put("testThatFails", parser.currentTestCase); String line = "t = 29.77s Assertion Failure: AppUITests.m:31: UI Testing Failure - No matches found for Alert"; parser.handleLine(line); assertEquals(1, parser.currentTestCase.getFailures().size()); assertEquals("AppUITests.m:31", parser.currentTestCase.getFailures().get(0).getLocation()); assertEquals("UI Testing Failure - No matches found for Alert", parser.currentTestCase.getFailures().get(0).getMessage()); } void shouldParsePassedTestCase() throws Exception { parser.currentTestSuite = new TestSuite("host", "PisClientTestCase", new Date()); parser.testSuitesHash.put("PisClientTestCase", parser.currentTestSuite); parser.currentTestCase = new TestCase("PisClientTestCase","testThatPasses"); parser.currentTestSuite.getTestCasesHash().put("testThatPasses", parser.currentTestCase); String line = "Test Case '-[PisClientTestCase testThatPasses]' passed (1.234 seconds)."; parser.handleLine(line); assertNull(parser.currentTestCase); assertEquals(1, parser.currentTestSuite.getTestCases().size()); assertEquals("testThatPasses", parser.currentTestSuite.getTestCases().get(0).getName()); assertEquals(1.234f, parser.currentTestSuite.getTestCases().get(0).getTime(),0); assertEquals(1,parser.currentTestSuite.getTests()); assertEquals(0,parser.currentTestSuite.getFailures()); } void shouldParseFailedTestCase() throws Exception { parser.currentTestSuite = new TestSuite("host", "PisClientTestCase", new Date()); parser.testSuitesHash.put("PisClientTestCase", parser.currentTestSuite); parser.currentTestCase = new TestCase("PisClientTestCase","testThatFails"); parser.currentTestSuite.getTestCasesHash().put("testThatFails", parser.currentTestCase); String line = "Test Case '-[PisClientTestCase testThatFails]' failed (1.234 seconds)."; parser.handleLine(line); assertNull(parser.currentTestCase); assertEquals(1, parser.currentTestSuite.getTestCases().size()); assertEquals("testThatFails", parser.currentTestSuite.getTestCases().get(0).getName()); assertEquals(1.234f, parser.currentTestSuite.getTestCases().get(0).getTime(),0); assertEquals(1,parser.currentTestSuite.getTests()); assertEquals(1,parser.currentTestSuite.getFailures()); } } ================================================ FILE: src/test/java/au/com/rayh/XCodeBuildHelpParserTest.java ================================================ package au.com.rayh; import org.junit.Assert; import org.apache.commons.io.FileUtils; import org.junit.Test; /** * Created by Kazuhide Takahashi on 4/26/18. */ public class XCodeBuildHelpParserTest { @Test public void testValidOutput() throws Throwable { String xcodeBuildOutput = FileUtils.readFileToString(FileUtils.toFile(ClassLoader.getSystemResource("xcodebuildhelp-valid.txt"))); XcodeBuildHelpParser parser = new XcodeBuildHelpParser(xcodeBuildOutput); Assert.assertEquals(2, parser.getParameters().size()); Assert.assertTrue(parser.getParameters().contains("-SampleTarget1")); Assert.assertTrue(parser.getParameters().contains("-TestSampleTarget1")); } @Test public void testInvalidOutputNull() throws Throwable { XcodeBuildHelpParser parser = new XcodeBuildHelpParser(null); Assert.assertEquals(0, parser.getParameters().size()); } @Test public void testInvalidOutputEmpty() throws Throwable { String xcodeBuildOutput = FileUtils.readFileToString(FileUtils.toFile(ClassLoader.getSystemResource("xcodebuildhelp-invalid.txt"))); XcodeBuildHelpParser parser = new XcodeBuildHelpParser(""); Assert.assertEquals(0, parser.getParameters().size()); } @Test public void testInvalidOutputExtraLine() throws Throwable { String xcodeBuildOutput = FileUtils.readFileToString(FileUtils.toFile(ClassLoader.getSystemResource("xcodebuildhelp-invalid.txt"))); XcodeBuildHelpParser parser = new XcodeBuildHelpParser(xcodeBuildOutput); Assert.assertEquals(0, parser.getParameters().size()); } } ================================================ FILE: src/test/java/au/com/rayh/XCodeBuildListParserTest.java ================================================ package au.com.rayh; import org.junit.Assert; import org.apache.commons.io.FileUtils; import org.junit.Test; /** * Created by timothy on 9/6/14. */ public class XCodeBuildListParserTest { @Test public void testValidOutput() throws Throwable { String xcodeBuildOutput = FileUtils.readFileToString(FileUtils.toFile(ClassLoader.getSystemResource("xcodebuildlist-valid.txt"))); XcodeBuildListParser parser = new XcodeBuildListParser(xcodeBuildOutput); Assert.assertEquals(4, parser.getTargets().size()); Assert.assertEquals(2, parser.getConfigurations().size()); Assert.assertEquals(2, parser.getSchemes().size()); Assert.assertTrue(parser.getTargets().contains("SampleTarget1")); Assert.assertTrue(parser.getTargets().contains("SampleTarget2")); Assert.assertTrue(parser.getTargets().contains("TestSampleTarget1")); Assert.assertTrue(parser.getTargets().contains("TestSampleTarget2")); Assert.assertTrue(parser.getConfigurations().contains("BuildConfiguration1")); Assert.assertTrue(parser.getConfigurations().contains("BuildConfiguration2")); Assert.assertTrue(parser.getSchemes().contains("SampleScheme1")); Assert.assertTrue(parser.getSchemes().contains("SampleScheme2")); } @Test public void testInvalidOutputNull() throws Throwable { XcodeBuildListParser parser = new XcodeBuildListParser(null); Assert.assertEquals(0, parser.getTargets().size()); Assert.assertEquals(0, parser.getConfigurations().size()); Assert.assertEquals(0, parser.getSchemes().size()); } @Test public void testInvalidOutputEmpty() throws Throwable { String xcodeBuildOutput = FileUtils.readFileToString(FileUtils.toFile(ClassLoader.getSystemResource("xcodebuildlist-invalid1.txt"))); XcodeBuildListParser parser = new XcodeBuildListParser(""); Assert.assertEquals(0, parser.getTargets().size()); Assert.assertEquals(0, parser.getConfigurations().size()); Assert.assertEquals(0, parser.getSchemes().size()); } @Test public void testInvalidOutputExtraLine() throws Throwable { String xcodeBuildOutput = FileUtils.readFileToString(FileUtils.toFile(ClassLoader.getSystemResource("xcodebuildlist-invalid1.txt"))); XcodeBuildListParser parser = new XcodeBuildListParser(xcodeBuildOutput); Assert.assertEquals(0, parser.getTargets().size()); Assert.assertEquals(0, parser.getConfigurations().size()); Assert.assertEquals(0, parser.getSchemes().size()); } @Test public void testInvalidOutputMissngColon() throws Throwable { String xcodeBuildOutput = FileUtils.readFileToString(FileUtils.toFile(ClassLoader.getSystemResource("xcodebuildlist-invalid2.txt"))); XcodeBuildListParser parser = new XcodeBuildListParser(xcodeBuildOutput); Assert.assertEquals(0, parser.getTargets().size()); Assert.assertEquals(0, parser.getConfigurations().size()); Assert.assertEquals(0, parser.getSchemes().size()); } } ================================================ FILE: src/test/java/au/com/rayh/XCodeBuildOutputParserTest.java ================================================ /* * The MIT License * * Copyright (c) 2011 Ray Yamamoto Hilton * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ /* * To change this template, choose Tools | Templates * and open the template in the editor. */ package au.com.rayh; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.PrintStream; import hudson.util.IOUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; /** * * @author ray */ public class XCodeBuildOutputParserTest { OutputParserTests test; @Before public void setUp() throws IOException, InterruptedException { XCodeBuildOutputParser parser = new XCodeBuildOutputParser(new File("."), new PrintStream("test-output.txt")); test = new OutputParserTests(parser); } @After public void tearDown() { } @Test public void shouldIgnoreStartSuiteLineThatContainsFullPath() throws Exception { test.shouldIgnoreStartSuiteLineThatContainsFullPath(); } @Test public void shouldParseStartTestSuite() throws Exception { test.shouldParseStartTestSuite(); } @Test public void shouldParseEndTestSuite() throws Exception { test.shouldParseEndTestSuite(); } @Test public void shouldParseStartTestSuiteXC() throws Exception { test.shouldParseStartTestSuiteXC(); } @Test public void shouldParseEndTestSuiteXC() throws Exception { test.shouldParseEndTestSuiteXC(); } @Test public void shouldParseStartTestCase() throws Exception { test.shouldParseStartTestCase(); } @Test public void shouldAddErrorToTestCase() throws Exception { test.shouldAddErrorToTestCase(); } @Test public void shouldAddUIErrorToTestCase() throws Exception { test.shouldAddUIErrorToTestCase(); } @Test public void shouldParsePassedTestCase() throws Exception { test.shouldParsePassedTestCase(); } @Test public void shouldParseFailedTestCase() throws Exception { test.shouldParseFailedTestCase(); } @Test public void shouldParseFullXCPassingTestOutput1() throws IOException { XCodeBuildOutputParser parser = parseTestOutput("/XCTest_output_passing_1.txt"); assertEquals(0, parser.getExitCode()); } @Test public void shouldParseFullXCFailingTestOutput1() throws IOException { XCodeBuildOutputParser parser = parseTestOutput("/XCTest_output_failing_1.txt"); assertEquals(-1, parser.getExitCode()); } //@Issue("JENKINS-26295") @Test public void shouldParseFullXCFailingTestOutput2() throws IOException { XCodeBuildOutputParser parser = parseTestOutput("/XCTest_output_failing_2.txt"); assertEquals(-1, parser.getExitCode()); } @Test public void shouldParseFullXCCrashingTestOutput1() throws IOException { XCodeBuildOutputParser parser = parseTestOutput("/XCTest_output_crashing_1.txt"); assertEquals(-1, parser.getExitCode()); } private XCodeBuildOutputParser parseTestOutput(String outputFileName) throws IOException { ByteArrayOutputStream output = new ByteArrayOutputStream(); XCodeBuildOutputParser parser = new XCodeBuildOutputParser(new File("."), output); IOUtils.copy(getClass().getResourceAsStream(outputFileName), parser.captureOutputStream); return parser; } // JENKINS-37072 @Test public void shouldParseFullXCPassingTestComplex1() throws IOException { XCodeBuildOutputParser parser = parseTestOutput("/XCTest_output_complex_1.txt"); assertEquals(-1, parser.getExitCode()); } // JENKINS-37072 @Test public void shouldParseFullXCPassingTestComplex2() throws IOException { XCodeBuildOutputParser parser = parseTestOutput("/XCTest_output_complex_2.txt"); assertEquals(-1, parser.getExitCode()); } } ================================================ FILE: src/test/java/au/com/rayh/XCodeBuilderTest.java ================================================ /* * The MIT License * * Copyright (c) 2012 Jerome Lacoste * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package au.com.rayh; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.Collections; import static org.junit.Assert.*; import static java.util.Arrays.asList; public class XCodeBuilderTest { @Before public void setUp() { } @After public void tearDown() { } @Test public void shouldSplitXcodeBuildArgumentsWithoutEscapedSpaces() throws Exception { assertEquals(Collections.singletonList("GCC_SYMBOLS_PRIVATE_EXTERN=NO"), XCodeBuilder.splitXcodeBuildArguments("GCC_SYMBOLS_PRIVATE_EXTERN=NO")); assertEquals(asList("GCC_SYMBOLS_PRIVATE_EXTERN=NO", "COPY_PHASE_STRIP=NO"), XCodeBuilder.splitXcodeBuildArguments("GCC_SYMBOLS_PRIVATE_EXTERN=NO COPY_PHASE_STRIP=NO")); } @Test public void shouldSplitXcodeBuildArgumentsWithEscapedSpaces() throws Exception { assertEquals(Collections.singletonList("CODE_SIGN_IDENTITY=iPhone Developer: Todd Kirby"), XCodeBuilder.splitXcodeBuildArguments("CODE_SIGN_IDENTITY=iPhone\\ Developer:\\ Todd\\ Kirby")); assertEquals(asList("A=B", "CODE_SIGN_IDENTITY=iPhone Developer: Todd Kirby"), XCodeBuilder.splitXcodeBuildArguments("A=B CODE_SIGN_IDENTITY=iPhone\\ Developer:\\ Todd\\ Kirby")); assertEquals(asList("A=B", "CODE_SIGN_IDENTITY=iPhone Distribution", "C=D"), XCodeBuilder.splitXcodeBuildArguments("A=B CODE_SIGN_IDENTITY=\"iPhone Distribution\" C=D")); } @Test public void shouldUnquoteWhenSplittingXcodeBuildArgumentsWithIncompleteDoubleQuote() throws Exception { assertEquals(asList("A=B", "CODE_SIGN_IDENTITY=iPhone Distribution"), XCodeBuilder.splitXcodeBuildArguments("A=B CODE_SIGN_IDENTITY=\"iPhone Distribution")); } @Test public void shouldUnquoteWhenSplittingXcodeBuildArgumentsWithIncompleteSingleQuote() throws Exception { assertEquals(asList("A=B", "CODE_SIGN_IDENTITY=iPhone"), XCodeBuilder.splitXcodeBuildArguments("A=B CODE_SIGN_IDENTITY='iPhone")); } } ================================================ FILE: src/test/java/au/com/rayh/XcodeProjectParserTest.java ================================================ package au.com.rayh; import org.junit.Assert; import org.apache.commons.io.FileUtils; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.io.File; import java.io.IOException; import java.net.URLDecoder; import java.util.Arrays; import org.junit.Assume; import org.junit.Rule; import org.junit.rules.TemporaryFolder; import hudson.FilePath; import hudson.Launcher.LocalLauncher; import hudson.util.StreamTaskListener; /** * Created by Kazuhide Takahashi on 1/22/18. */ public class XcodeProjectParserTest { @Rule public TemporaryFolder tmp = new TemporaryFolder(); @Test public void testValidProject() throws Throwable { File dir = tmp.getRoot(); FilePath workspace = new FilePath(dir); String projectLocation = URLDecoder.decode(XcodeProjectParserTest.class.getClassLoader().getResource("XcodeProject.tar.gz").getPath(), "UTF-8"); run(workspace, "tar", "zxvpf", projectLocation); FilePath projectPath = workspace.child("TestXcodeProject.xcodeproj"); Assert.assertNotNull(projectPath); HashMap xcodeSchemes = XcodeProjectParser.listXcodeSchemes(projectPath); Assert.assertNotNull(xcodeSchemes); Assert.assertEquals(1, xcodeSchemes.size()); String xcodeSchema = "TestXcodeProject"; Assert.assertTrue(xcodeSchemes.containsKey(xcodeSchema)); ProjectScheme projectScheme = xcodeSchemes.get(xcodeSchema); Assert.assertEquals("container:TestXcodeProject.xcodeproj", projectScheme.referencedContainer); Assert.assertEquals("TestXcodeProject", projectScheme.blueprintName); FilePath workspacePath = workspace.child("TestXcodeProject.xcworkspace"); Assert.assertNotNull(workspacePath); List projectList = XcodeProjectParser.parseXcodeWorkspace(workspacePath); Assert.assertNotNull(projectList); Assert.assertEquals(1, projectList.size()); Assert.assertTrue(projectList.contains("TestXcodeProject.xcodeproj")); XcodeProject xcodeProject = XcodeProjectParser.parseXcodeProject(projectPath); Assert.assertNotNull(xcodeProject.projectTarget.get("TestXcodeProject")); Assert.assertNotNull(xcodeProject.projectTarget.get("TestXcodeProjectTests")); Assert.assertNotNull(xcodeProject.projectTarget.get("TestXcodeProjectTests")); } @Test public void testInvalidProject() throws Throwable { } private static void run(FilePath dir, String... cmds) throws InterruptedException { try { Assert.assertEquals(0, new LocalLauncher(StreamTaskListener.fromStdout()).launch().cmds(cmds).pwd(dir).join()); } catch (IOException x) { // perhaps restrict to x.message.contains("Cannot run program")? or "error=2, No such file or directory"? Assume.assumeNoException("failed to run " + Arrays.toString(cmds), x); } } } ================================================ FILE: src/test/java/au/com/rayh/XcodeTestSummariesParserTest.java ================================================ package au.com.rayh; import org.junit.Assert; import org.apache.commons.io.FileUtils; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.io.File; import java.io.IOException; import java.net.URLDecoder; import java.util.Arrays; import org.junit.Assume; import org.junit.Rule; import org.junit.rules.TemporaryFolder; import hudson.FilePath; import hudson.Launcher.LocalLauncher; import hudson.util.StreamTaskListener; /** * Created by Kazuhide Takahashi on 1/7/19. */ public class XcodeTestSummariesParserTest { @Rule public TemporaryFolder tmp = new TemporaryFolder(); @Test public void testValidTestSummaries() throws Throwable { File dir = tmp.getRoot(); FilePath workspace = new FilePath(dir); String projectLocation = URLDecoder.decode(XcodeTestSummariesParserTest.class.getClassLoader().getResource("XcodeTestSummaries.tar.gz").getPath(), "UTF-8"); run(workspace, "tar", "zxvpf", projectLocation); FilePath testSummariesPath = workspace.child("result/TestSummaries.plist"); Assert.assertNotNull(testSummariesPath); XcodeTestSummariesParser parser = new XcodeTestSummariesParser(new FilePath(new File("."))); Assert.assertNotNull(parser); parser.parseTestSummariesPlist(testSummariesPath); } @Test public void testInvalidTestSummaries() throws Throwable { } private static void run(FilePath dir, String... cmds) throws InterruptedException { try { Assert.assertEquals(0, new LocalLauncher(StreamTaskListener.fromStdout()).launch().cmds(cmds).pwd(dir).join()); } catch (IOException x) { // perhaps restrict to x.message.contains("Cannot run program")? or "error=2, No such file or directory"? Assume.assumeNoException("failed to run " + Arrays.toString(cmds), x); } } } ================================================ FILE: src/test/resources/XCTest_output_complex_1.txt ================================================ Test Suite 'All tests' started at 2018-05-17 07:07:31.814 Test Suite 'XCUITests-ExampleTests.xctest' started at 2018-05-17 07:07:31.815 Test Suite 'Objc_Test_Under_Score_Tests' started at 2018-05-17 07:07:31.816 Test Case '-[Objc_Test_Under_Score_Tests testExample]' started. Test Case '-[Objc_Test_Under_Score_Tests testExample]' passed (0.001 seconds). Test Case '-[Objc_Test_Under_Score_Tests testPerformanceExample]' started. Test Case '-[Objc_Test_Under_Score_Tests testPerformanceExample]' passed (0.339 seconds). Test Suite 'Objc_Test_Under_Score_Tests' passed at 2018-05-17 07:07:32.157. Test Suite 'Objec_SubTests' started at 2018-05-17 07:07:32.157 Test Case '-[Objec_SubTests testExample]' started. Test Case '-[Objec_SubTests testExample]' passed (0.000 seconds). Test Case '-[Objec_SubTests testPerformanceExample]' started. Test Case '-[Objec_SubTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'Objec_SubTests' passed at 2018-05-17 07:07:32.410. Test Suite 'RaiseAnExceptionTests' started at 2018-05-17 07:07:32.411 Test Case '-[RaiseAnExceptionTests testExample1]' started. /Volumes/RAID10HDD/iOS/XCUITests_Example/XCUITests_ExampleTests/RaiseAnExceptionTests.m:32: error: -[RaiseAnExceptionTests testExample1] : failed: caught "NSRangeException", "*** -[__NSArrayI objectAtIndex:]: index 11 beyond bounds [0 .. 2]" Test Case '-[RaiseAnExceptionTests testExample1]' failed (0.015 seconds). Test Case '-[RaiseAnExceptionTests testExample2]' started. /Volumes/RAID10HDD/iOS/XCUITests_Example/XCUITests_ExampleTests/RaiseAnExceptionTests.m:40: error: -[RaiseAnExceptionTests testExample2] : ((result) equal to (@"value1")) failed: ("value2") is not equal to ("value1") Test Case '-[RaiseAnExceptionTests testExample2]' failed (0.001 seconds). Test Case '-[RaiseAnExceptionTests testExample3]' started. Test Case '-[RaiseAnExceptionTests testExample3]' passed (0.000 seconds). Test Case '-[RaiseAnExceptionTests testPerformanceExample]' started. Test Case '-[RaiseAnExceptionTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'RaiseAnExceptionTests' failed at 2018-05-17 07:07:32.681. Test Suite 'Swift_SubTests' started at 2018-05-17 07:07:32.682 Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample1]' started. :0: error: -[XCUITests_ExampleTests.Swift_SubTests testExample1] : failed: caught "NSRangeException", "*** -[__NSArrayI objectAtIndex:]: index 10 beyond bounds [0 .. 2]" Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample1]' failed (0.013 seconds). Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample2]' started. /Volumes/RAID10HDD/iOS/XCUITests_Example/XCUITests_ExampleTests/SubTests/Swift_SubTests.swift:36: error: -[XCUITests_ExampleTests.Swift_SubTests testExample2] : XCTAssertEqual failed: ("Optional("value2")") is not equal to ("Optional("value1")") - Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample2]' failed (0.005 seconds). Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample3]' started. Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample3]' passed (0.000 seconds). Test Case '-[XCUITests_ExampleTests.Swift_SubTests testPerformanceExample]' started. Test Case '-[XCUITests_ExampleTests.Swift_SubTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'Swift_SubTests' failed at 2018-05-17 07:07:32.955. Test Suite 'Swift_Test_Under_Score_Tests' started at 2018-05-17 07:07:32.956 Test Case '-[XCUITests_ExampleTests.Swift_Test_Under_Score_Tests testExample]' started. Test Case '-[XCUITests_ExampleTests.Swift_Test_Under_Score_Tests testExample]' passed (0.001 seconds). Test Case '-[XCUITests_ExampleTests.Swift_Test_Under_Score_Tests testPerformanceExample]' started. Test Case '-[XCUITests_ExampleTests.Swift_Test_Under_Score_Tests testPerformanceExample]' passed (0.252 seconds). Test Suite 'Swift_Test_Under_Score_Tests' passed at 2018-05-17 07:07:33.210. Test Suite 'XCUITests_AnotherTests' started at 2018-05-17 07:07:33.210 Test Case '-[XCUITests_AnotherTests testExample]' started. Test Case '-[XCUITests_AnotherTests testExample]' passed (0.001 seconds). Test Case '-[XCUITests_AnotherTests testPerformanceExample]' started. Test Case '-[XCUITests_AnotherTests testPerformanceExample]' passed (0.253 seconds). Test Suite 'XCUITests_AnotherTests' passed at 2018-05-17 07:07:33.464. Test Suite 'XCUITests_ExampleTests' started at 2018-05-17 07:07:33.465 Test Case '-[XCUITests_ExampleTests testExample]' started. Test Case '-[XCUITests_ExampleTests testExample]' passed (0.001 seconds). Test Case '-[XCUITests_ExampleTests testPerformanceExample]' started. Test Case '-[XCUITests_ExampleTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'XCUITests_ExampleTests' passed at 2018-05-17 07:07:33.718. Test Suite 'XCUITests_SubTests' started at 2018-05-17 07:07:33.719 Test Case '-[XCUITests_SubTests testExample]' started. Test Case '-[XCUITests_SubTests testExample]' passed (0.000 seconds). Test Case '-[XCUITests_SubTests testPerformanceExample]' started. Test Case '-[XCUITests_SubTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'XCUITests_SubTests' passed at 2018-05-17 07:07:33.972. Test Suite 'XCUITests_SwiftTests' started at 2018-05-17 07:07:33.973 Test Case '-[XCUITests_ExampleTests.XCUITests_SwiftTests testExample]' started. Test Case '-[XCUITests_ExampleTests.XCUITests_SwiftTests testExample]' passed (0.001 seconds). Test Case '-[XCUITests_ExampleTests.XCUITests_SwiftTests testPerformanceExample]' started. Test Case '-[XCUITests_ExampleTests.XCUITests_SwiftTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'XCUITests_SwiftTests' passed at 2018-05-17 07:07:34.227. Test Suite 'XCUITests-ExampleTests.xctest' failed at 2018-05-17 07:07:34.227. Test Suite 'All tests' failed at 2018-05-17 07:07:34.228. Test Suite 'All tests' started at 2018-05-17 07:07:40.691 Test Suite 'XCUITests-ExampleUITests.xctest' started at 2018-05-17 07:07:40.692 Test Suite 'XCUITests_ExampleUITests' started at 2018-05-17 07:07:40.693 Test Case '-[XCUITests_ExampleUITests testExample]' started. t = 0.00s Start Test at 2018-05-17 07:07:40.693 t = 0.07s Set Up t = 0.07s Open net.hoge2.XCUITests-Example t = 0.12s Launch net.hoge2.XCUITests-Example t = 5.04s Wait for net.hoge2.XCUITests-Example to idle t = 6.21s Tap "Add" Button t = 6.22s Wait for net.hoge2.XCUITests-Example to idle t = 6.26s Find the "Add" Button t = 6.26s Snapshot accessibility hierarchy for app with pid 39901 t = 6.30s Find: Descendants matching type NavigationBar t = 6.30s Find: Elements matching predicate '"Master" IN identifiers' t = 6.31s Find: Descendants matching type Button t = 6.31s Find: Elements matching predicate '"Add" IN identifiers' t = 6.41s Wait for net.hoge2.XCUITests-Example to idle t = 6.46s Synthesize event t = 6.59s Wait for net.hoge2.XCUITests-Example to idle t = 7.08s Tap "Add" Button t = 7.08s Wait for net.hoge2.XCUITests-Example to idle t = 7.12s Find the "Add" Button t = 7.13s Snapshot accessibility hierarchy for app with pid 39901 t = 7.15s Find: Descendants matching type NavigationBar t = 7.15s Find: Elements matching predicate '"Master" IN identifiers' t = 7.16s Find: Descendants matching type Button t = 7.16s Find: Elements matching predicate '"Add" IN identifiers' t = 7.26s Wait for net.hoge2.XCUITests-Example to idle t = 7.31s Synthesize event t = 7.43s Wait for net.hoge2.XCUITests-Example to idle t = 7.90s Tap Cell t = 7.90s Wait for net.hoge2.XCUITests-Example to idle t = 7.95s Find the Cell t = 7.95s Snapshot accessibility hierarchy for app with pid 39901 t = 7.98s Find: Descendants matching type Table t = 7.98s Find: Descendants matching type Cell t = 7.98s Find: Element at index 0 t = 8.08s Wait for net.hoge2.XCUITests-Example to idle t = 8.13s Synthesize event t = 8.26s Wait for net.hoge2.XCUITests-Example to idle t = 8.79s Tap "Master" Button t = 8.79s Wait for net.hoge2.XCUITests-Example to idle t = 8.85s Find the "Master" Button t = 8.85s Snapshot accessibility hierarchy for app with pid 39901 t = 8.87s Find: Descendants matching type NavigationBar t = 8.87s Find: Elements matching predicate '"Detail" IN identifiers' t = 8.87s Find: Descendants matching type Button t = 8.87s Find: Elements matching predicate '"Master" IN identifiers' t = 8.98s Wait for net.hoge2.XCUITests-Example to idle t = 9.03s Synthesize event t = 9.15s Wait for net.hoge2.XCUITests-Example to idle t = 9.67s Tap Cell t = 9.67s Wait for net.hoge2.XCUITests-Example to idle t = 9.73s Find the Cell t = 9.73s Snapshot accessibility hierarchy for app with pid 39901 t = 9.75s Find: Descendants matching type Table t = 9.75s Find: Descendants matching type Cell t = 9.75s Find: Element at index 1 t = 9.86s Wait for net.hoge2.XCUITests-Example to idle t = 9.91s Synthesize event t = 10.03s Wait for net.hoge2.XCUITests-Example to idle t = 10.56s Tap "Master" Button t = 10.56s Wait for net.hoge2.XCUITests-Example to idle t = 10.62s Find the "Master" Button t = 10.62s Snapshot accessibility hierarchy for app with pid 39901 t = 10.64s Find: Descendants matching type NavigationBar t = 10.64s Find: Elements matching predicate '"Detail" IN identifiers' t = 10.64s Find: Descendants matching type Button t = 10.64s Find: Elements matching predicate '"Master" IN identifiers' t = 10.75s Wait for net.hoge2.XCUITests-Example to idle t = 10.80s Synthesize event t = 10.92s Wait for net.hoge2.XCUITests-Example to idle t = 11.44s Tap "Edit" Button t = 11.44s Wait for net.hoge2.XCUITests-Example to idle t = 11.49s Find the "Edit" Button t = 11.50s Snapshot accessibility hierarchy for app with pid 39901 t = 11.52s Find: Descendants matching type NavigationBar t = 11.52s Find: Elements matching predicate '"Master" IN identifiers' t = 11.52s Find: Descendants matching type Button t = 11.52s Find: Elements matching predicate '"Edit" IN identifiers' t = 11.63s Wait for net.hoge2.XCUITests-Example to idle t = 11.67s Synthesize event t = 11.79s Wait for net.hoge2.XCUITests-Example to idle t = 12.28s Tap "Done" Button t = 12.28s Wait for net.hoge2.XCUITests-Example to idle t = 12.33s Find the "Done" Button t = 12.33s Snapshot accessibility hierarchy for app with pid 39901 t = 12.36s Find: Descendants matching type NavigationBar t = 12.36s Find: Elements matching predicate '"Master" IN identifiers' t = 12.36s Find: Descendants matching type Button t = 12.36s Find: Elements matching predicate '"Done" IN identifiers' t = 12.47s Wait for net.hoge2.XCUITests-Example to idle t = 12.52s Synthesize event t = 12.64s Wait for net.hoge2.XCUITests-Example to idle t = 13.11s Tear Down Test Case '-[XCUITests_ExampleUITests testExample]' passed (13.316 seconds). Test Suite 'XCUITests_ExampleUITests' passed at 2018-05-17 07:07:54.010. Test Suite 'XCUITests_ExampleUITestsFail' started at 2018-05-17 07:07:54.011 Test Case '-[XCUITests_ExampleUITestsFail testExample]' started. t = 0.00s Start Test at 2018-05-17 07:07:54.012 t = 0.05s Set Up t = 0.15s Open net.hoge2.XCUITests-Example t = 0.19s Launch net.hoge2.XCUITests-Example t = 0.19s Terminate net.hoge2.XCUITests-Example:39901 t = 5.29s Wait for net.hoge2.XCUITests-Example to idle t = 6.45s Tap "Add" Button t = 6.45s Wait for net.hoge2.XCUITests-Example to idle t = 6.49s Find the "Add" Button t = 6.50s Snapshot accessibility hierarchy for app with pid 39907 t = 6.53s Find: Descendants matching type NavigationBar t = 6.54s Find: Elements matching predicate '"Master" IN identifiers' t = 6.54s Find: Descendants matching type Button t = 6.54s Find: Elements matching predicate '"Add" IN identifiers' t = 6.64s Wait for net.hoge2.XCUITests-Example to idle t = 6.69s Synthesize event t = 6.82s Wait for net.hoge2.XCUITests-Example to idle t = 7.30s Tap "Add" Button t = 7.30s Wait for net.hoge2.XCUITests-Example to idle t = 7.35s Find the "Add" Button t = 7.35s Snapshot accessibility hierarchy for app with pid 39907 t = 7.38s Find: Descendants matching type NavigationBar t = 7.38s Find: Elements matching predicate '"Master" IN identifiers' t = 7.38s Find: Descendants matching type Button t = 7.38s Find: Elements matching predicate '"Add" IN identifiers' t = 7.49s Wait for net.hoge2.XCUITests-Example to idle t = 7.54s Synthesize event t = 7.66s Wait for net.hoge2.XCUITests-Example to idle t = 8.13s Tap Cell t = 8.13s Wait for net.hoge2.XCUITests-Example to idle t = 8.18s Find the Cell t = 8.18s Snapshot accessibility hierarchy for app with pid 39907 t = 8.20s Find: Descendants matching type Table t = 8.20s Find: Descendants matching type Cell t = 8.21s Find: Element at index 0 t = 8.31s Wait for net.hoge2.XCUITests-Example to idle t = 8.36s Synthesize event t = 8.49s Wait for net.hoge2.XCUITests-Example to idle t = 9.02s Tap "Master" Button t = 9.02s Wait for net.hoge2.XCUITests-Example to idle t = 9.08s Find the "Master" Button t = 9.08s Snapshot accessibility hierarchy for app with pid 39907 t = 9.10s Find: Descendants matching type NavigationBar t = 9.10s Find: Elements matching predicate '"Detail" IN identifiers' t = 9.10s Find: Descendants matching type Button t = 9.10s Find: Elements matching predicate '"Master" IN identifiers' t = 9.21s Wait for net.hoge2.XCUITests-Example to idle t = 9.26s Synthesize event t = 9.38s Wait for net.hoge2.XCUITests-Example to idle t = 9.90s Tap Cell t = 9.90s Wait for net.hoge2.XCUITests-Example to idle t = 9.95s Find the Cell t = 9.95s Snapshot accessibility hierarchy for app with pid 39907 t = 9.98s Find: Descendants matching type Table t = 9.98s Find: Descendants matching type Cell t = 9.98s Find: Element at index 1 t = 10.08s Wait for net.hoge2.XCUITests-Example to idle t = 10.13s Synthesize event t = 10.26s Wait for net.hoge2.XCUITests-Example to idle t = 10.78s Tap "Master" Button t = 10.78s Wait for net.hoge2.XCUITests-Example to idle t = 10.83s Find the "Master" Button t = 10.83s Snapshot accessibility hierarchy for app with pid 39907 t = 10.85s Find: Descendants matching type NavigationBar t = 10.85s Find: Elements matching predicate '"Detail" IN identifiers' t = 10.85s Find: Descendants matching type Button t = 10.85s Find: Elements matching predicate '"Master" IN identifiers' t = 10.96s Wait for net.hoge2.XCUITests-Example to idle t = 11.01s Synthesize event t = 11.12s Wait for net.hoge2.XCUITests-Example to idle t = 11.64s Tap "Edit" Button t = 11.64s Wait for net.hoge2.XCUITests-Example to idle t = 11.69s Find the "Edit" Button t = 11.69s Snapshot accessibility hierarchy for app with pid 39907 t = 11.71s Find: Descendants matching type NavigationBar t = 11.71s Find: Elements matching predicate '"Master" IN identifiers' t = 11.72s Find: Descendants matching type Button t = 11.72s Find: Elements matching predicate '"Edit" IN identifiers' t = 11.82s Wait for net.hoge2.XCUITests-Example to idle t = 11.87s Synthesize event t = 11.99s Wait for net.hoge2.XCUITests-Example to idle t = 12.47s Tap Cell t = 12.47s Wait for net.hoge2.XCUITests-Example to idle t = 12.52s Find the Cell t = 12.52s Snapshot accessibility hierarchy for app with pid 39907 t = 12.54s Find: Descendants matching type Table t = 12.54s Find: Descendants matching type Cell t = 12.54s Find: Element at index 0 t = 12.65s Wait for net.hoge2.XCUITests-Example to idle t = 12.70s Synthesize event t = 12.82s Wait for net.hoge2.XCUITests-Example to idle t = 12.87s Tap "Delete" Button t = 12.87s Wait for net.hoge2.XCUITests-Example to idle t = 12.91s Find the "Delete" Button t = 12.92s Snapshot accessibility hierarchy for app with pid 39907 t = 12.94s Find: Descendants matching type Table t = 12.94s Find: Descendants matching type Button t = 12.94s Find: Elements matching predicate '"Delete" IN identifiers' t = 13.05s Wait for net.hoge2.XCUITests-Example to idle t = 14.10s Find the "Delete" Button (retry 1) t = 14.10s Snapshot accessibility hierarchy for app with pid 39907 t = 14.12s Find: Descendants matching type Table t = 14.13s Find: Descendants matching type Button t = 14.13s Find: Elements matching predicate '"Delete" IN identifiers' t = 14.23s Wait for net.hoge2.XCUITests-Example to idle t = 15.28s Find the "Delete" Button (retry 2) t = 15.29s Snapshot accessibility hierarchy for app with pid 39907 t = 15.31s Find: Descendants matching type Table t = 15.31s Find: Descendants matching type Button t = 15.31s Find: Elements matching predicate '"Delete" IN identifiers' t = 15.42s Wait for net.hoge2.XCUITests-Example to idle t = 15.52s Assertion Failure: XCUITests_ExampleUITestsFail.m:57: No matches found for Find: Elements matching predicate '"Delete" IN identifiers' from input {( ** TEST FAILED ** t = 15.56s Tear Down Test Case '-[XCUITests_ExampleUITestsFail testExample]' failed (15.769 seconds). Test Suite 'XCUITests_ExampleUITestsFail' failed at 2018-05-17 07:08:09.782. Test Suite 'XCUITests_SubUITests' started at 2018-05-17 07:08:09.783 Test Case '-[XCUITests_SubUITests testExample]' started. t = 0.00s Start Test at 2018-05-17 07:08:09.784 t = 0.04s Set Up t = 0.14s Open net.hoge2.XCUITests-Example t = 0.18s Launch net.hoge2.XCUITests-Example t = 0.18s Terminate net.hoge2.XCUITests-Example:39907 t = 5.27s Wait for net.hoge2.XCUITests-Example to idle t = 6.46s Tap "Add" Button t = 6.46s Wait for net.hoge2.XCUITests-Example to idle t = 6.51s Find the "Add" Button t = 6.51s Snapshot accessibility hierarchy for app with pid 39915 t = 6.55s Find: Descendants matching type NavigationBar t = 6.55s Find: Elements matching predicate '"Master" IN identifiers' t = 6.55s Find: Descendants matching type Button t = 6.56s Find: Elements matching predicate '"Add" IN identifiers' t = 6.66s Wait for net.hoge2.XCUITests-Example to idle t = 6.71s Synthesize event t = 6.85s Wait for net.hoge2.XCUITests-Example to idle t = 7.33s Tap "Add" Button t = 7.33s Wait for net.hoge2.XCUITests-Example to idle t = 7.39s Find the "Add" Button t = 7.39s Snapshot accessibility hierarchy for app with pid 39915 t = 7.42s Find: Descendants matching type NavigationBar t = 7.42s Find: Elements matching predicate '"Master" IN identifiers' t = 7.42s Find: Descendants matching type Button t = 7.42s Find: Elements matching predicate '"Add" IN identifiers' t = 7.53s Wait for net.hoge2.XCUITests-Example to idle t = 7.57s Synthesize event t = 7.69s Wait for net.hoge2.XCUITests-Example to idle t = 8.17s Tap Cell t = 8.17s Wait for net.hoge2.XCUITests-Example to idle t = 8.22s Find the Cell t = 8.22s Snapshot accessibility hierarchy for app with pid 39915 t = 8.24s Find: Descendants matching type Table t = 8.24s Find: Descendants matching type Cell t = 8.24s Find: Element at index 0 t = 8.35s Wait for net.hoge2.XCUITests-Example to idle t = 8.40s Synthesize event t = 8.52s Wait for net.hoge2.XCUITests-Example to idle t = 9.06s Tap "Master" Button t = 9.06s Wait for net.hoge2.XCUITests-Example to idle t = 9.12s Find the "Master" Button t = 9.12s Snapshot accessibility hierarchy for app with pid 39915 t = 9.15s Find: Descendants matching type NavigationBar t = 9.15s Find: Elements matching predicate '"Detail" IN identifiers' t = 9.15s Find: Descendants matching type Button t = 9.15s Find: Elements matching predicate '"Master" IN identifiers' t = 9.26s Wait for net.hoge2.XCUITests-Example to idle t = 9.31s Synthesize event t = 9.44s Wait for net.hoge2.XCUITests-Example to idle t = 9.95s Tap Cell t = 9.95s Wait for net.hoge2.XCUITests-Example to idle t = 10.01s Find the Cell t = 10.01s Snapshot accessibility hierarchy for app with pid 39915 t = 10.03s Find: Descendants matching type Table t = 10.04s Find: Descendants matching type Cell t = 10.04s Find: Element at index 1 t = 10.14s Wait for net.hoge2.XCUITests-Example to idle t = 10.20s Synthesize event t = 10.33s Wait for net.hoge2.XCUITests-Example to idle t = 10.85s Tap "Master" Button t = 10.85s Wait for net.hoge2.XCUITests-Example to idle t = 10.90s Find the "Master" Button t = 10.90s Snapshot accessibility hierarchy for app with pid 39915 t = 10.92s Find: Descendants matching type NavigationBar t = 10.93s Find: Elements matching predicate '"Detail" IN identifiers' t = 10.93s Find: Descendants matching type Button t = 10.93s Find: Elements matching predicate '"Master" IN identifiers' t = 11.04s Wait for net.hoge2.XCUITests-Example to idle t = 11.09s Synthesize event t = 11.21s Wait for net.hoge2.XCUITests-Example to idle t = 11.72s Tap "Edit" Button t = 11.72s Wait for net.hoge2.XCUITests-Example to idle t = 11.78s Find the "Edit" Button t = 11.78s Snapshot accessibility hierarchy for app with pid 39915 t = 11.81s Find: Descendants matching type NavigationBar t = 11.81s Find: Elements matching predicate '"Master" IN identifiers' t = 11.81s Find: Descendants matching type Button t = 11.81s Find: Elements matching predicate '"Edit" IN identifiers' t = 11.91s Wait for net.hoge2.XCUITests-Example to idle t = 11.96s Synthesize event t = 12.08s Wait for net.hoge2.XCUITests-Example to idle t = 12.56s Tap "Done" Button t = 12.56s Wait for net.hoge2.XCUITests-Example to idle t = 12.62s Find the "Done" Button t = 12.62s Snapshot accessibility hierarchy for app with pid 39915 t = 12.65s Find: Descendants matching type NavigationBar t = 12.65s Find: Elements matching predicate '"Master" IN identifiers' t = 12.65s Find: Descendants matching type Button t = 12.65s Find: Elements matching predicate '"Done" IN identifiers' t = 12.76s Wait for net.hoge2.XCUITests-Example to idle t = 12.81s Synthesize event t = 12.93s Wait for net.hoge2.XCUITests-Example to idle t = 13.41s Tear Down Test Case '-[XCUITests_SubUITests testExample]' passed (13.610 seconds). Test Suite 'XCUITests_SubUITests' passed at 2018-05-17 07:08:23.394. Test Suite 'XCUITests-ExampleUITests.xctest' failed at 2018-05-17 07:08:23.395. Test Suite 'All tests' failed at 2018-05-17 07:08:23.396. ================================================ FILE: src/test/resources/XCTest_output_complex_2.txt ================================================ Test Suite 'All tests' started at 2018-05-17 07:07:31.814 Test Suite 'XCUITests-ExampleTests.xctest' started at 2018-05-17 07:07:31.815 Test Suite 'Objc_Test_Under_Score_Tests' started at 2018-05-17 07:07:31.816 Test Case '-[Objc_Test_Under_Score_Tests testExample]' started. Test Case '-[Objc_Test_Under_Score_Tests testExample]' passed (0.001 seconds). Test Case '-[Objc_Test_Under_Score_Tests testPerformanceExample]' started. Test Case '-[Objc_Test_Under_Score_Tests testPerformanceExample]' passed (0.339 seconds). Test Suite 'Objc_Test_Under_Score_Tests' passed at 2018-05-17 07:07:32.157. Test Suite 'Objec_SubTests' started at 2018-05-17 07:07:32.157 Test Case '-[Objec_SubTests testExample]' started. Test Case '-[Objec_SubTests testExample]' passed (0.000 seconds). Test Case '-[Objec_SubTests testPerformanceExample]' started. Test Case '-[Objec_SubTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'Objec_SubTests' passed at 2018-05-17 07:07:32.410. Test Suite 'RaiseAnExceptionTests' started at 2018-05-17 07:07:32.411 Test Case '-[RaiseAnExceptionTests testExample1]' started. /Volumes/RAID10HDD/iOS/XCUITests_Example/XCUITests_ExampleTests/RaiseAnExceptionTests.m:32: error: -[RaiseAnExceptionTests testExample1] : failed: caught "NSRangeException", "*** -[__NSArrayI objectAtIndex:]: index 11 beyond bounds [0 .. 2]" Test Case '-[RaiseAnExceptionTests testExample2]' started. /Volumes/RAID10HDD/iOS/XCUITests_Example/XCUITests_ExampleTests/RaiseAnExceptionTests.m:40: error: -[RaiseAnExceptionTests testExample2] : ((result) equal to (@"value1")) failed: ("value2") is not equal to ("value1") Test Case '-[RaiseAnExceptionTests testExample2]' failed (0.001 seconds). Test Case '-[RaiseAnExceptionTests testExample3]' started. Test Case '-[RaiseAnExceptionTests testExample1]' failed (0.015 seconds). Test Case '-[RaiseAnExceptionTests testExample3]' passed (0.000 seconds). Test Case '-[RaiseAnExceptionTests testPerformanceExample]' started. Test Case '-[RaiseAnExceptionTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'RaiseAnExceptionTests' failed at 2018-05-17 07:07:32.681. Test Suite 'Swift_SubTests' started at 2018-05-17 07:07:32.682 Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample1]' started. Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample1]' failed (0.013 seconds). :0: error: -[XCUITests_ExampleTests.Swift_SubTests testExample1] : failed: caught "NSRangeException", "*** -[__NSArrayI objectAtIndex:]: index 10 beyond bounds [0 .. 2]" Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample2]' started. /Volumes/RAID10HDD/iOS/XCUITests_Example/XCUITests_ExampleTests/SubTests/Swift_SubTests.swift:36: error: -[XCUITests_ExampleTests.Swift_SubTests testExample2] : XCTAssertEqual failed: ("Optional("value2")") is not equal to ("Optional("value1")") - Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample2]' failed (0.005 seconds). Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample3]' started. Test Case '-[XCUITests_ExampleTests.Swift_SubTests testExample3]' passed (0.000 seconds). Test Case '-[XCUITests_ExampleTests.Swift_SubTests testPerformanceExample]' started. Test Case '-[XCUITests_ExampleTests.Swift_SubTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'Swift_SubTests' failed at 2018-05-17 07:07:32.955. Test Suite 'Swift_Test_Under_Score_Tests' started at 2018-05-17 07:07:32.956 Test Case '-[XCUITests_ExampleTests.Swift_Test_Under_Score_Tests testExample]' started. Test Case '-[XCUITests_ExampleTests.Swift_Test_Under_Score_Tests testExample]' passed (0.001 seconds). Test Case '-[XCUITests_ExampleTests.Swift_Test_Under_Score_Tests testPerformanceExample]' started. Test Case '-[XCUITests_ExampleTests.Swift_Test_Under_Score_Tests testPerformanceExample]' passed (0.252 seconds). Test Suite 'Swift_Test_Under_Score_Tests' passed at 2018-05-17 07:07:33.210. Test Suite 'XCUITests_AnotherTests' started at 2018-05-17 07:07:33.210 Test Case '-[XCUITests_AnotherTests testExample]' started. Test Case '-[XCUITests_AnotherTests testExample]' passed (0.001 seconds). Test Case '-[XCUITests_AnotherTests testPerformanceExample]' started. Test Case '-[XCUITests_AnotherTests testPerformanceExample]' passed (0.253 seconds). Test Suite 'XCUITests_AnotherTests' passed at 2018-05-17 07:07:33.464. Test Suite 'XCUITests_ExampleTests' started at 2018-05-17 07:07:33.465 Test Case '-[XCUITests_ExampleTests testExample]' started. Test Case '-[XCUITests_ExampleTests testExample]' passed (0.001 seconds). Test Case '-[XCUITests_ExampleTests testPerformanceExample]' started. Test Case '-[XCUITests_ExampleTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'XCUITests_ExampleTests' passed at 2018-05-17 07:07:33.718. Test Suite 'XCUITests_SubTests' started at 2018-05-17 07:07:33.719 Test Case '-[XCUITests_SubTests testExample]' started. Test Case '-[XCUITests_SubTests testExample]' passed (0.000 seconds). Test Case '-[XCUITests_SubTests testPerformanceExample]' started. Test Case '-[XCUITests_SubTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'XCUITests_SubTests' passed at 2018-05-17 07:07:33.972. Test Suite 'XCUITests_SwiftTests' started at 2018-05-17 07:07:33.973 Test Case '-[XCUITests_ExampleTests.XCUITests_SwiftTests testExample]' started. Test Case '-[XCUITests_ExampleTests.XCUITests_SwiftTests testExample]' passed (0.001 seconds). Test Case '-[XCUITests_ExampleTests.XCUITests_SwiftTests testPerformanceExample]' started. Test Case '-[XCUITests_ExampleTests.XCUITests_SwiftTests testPerformanceExample]' passed (0.252 seconds). Test Suite 'XCUITests_SwiftTests' passed at 2018-05-17 07:07:34.227. Test Suite 'XCUITests-ExampleTests.xctest' failed at 2018-05-17 07:07:34.227. Test Suite 'All tests' failed at 2018-05-17 07:07:34.228. Test Suite 'All tests' started at 2018-05-17 07:07:40.691 Test Suite 'XCUITests-ExampleUITests.xctest' started at 2018-05-17 07:07:40.692 Test Suite 'XCUITests_ExampleUITests' started at 2018-05-17 07:07:40.693 Test Case '-[XCUITests_ExampleUITests testExample]' started. t = 0.00s Start Test at 2018-05-17 07:07:40.693 t = 0.07s Set Up t = 0.07s Open net.hoge2.XCUITests-Example t = 0.12s Launch net.hoge2.XCUITests-Example t = 5.04s Wait for net.hoge2.XCUITests-Example to idle t = 6.21s Tap "Add" Button t = 6.22s Wait for net.hoge2.XCUITests-Example to idle t = 6.26s Find the "Add" Button t = 6.26s Snapshot accessibility hierarchy for app with pid 39901 t = 6.30s Find: Descendants matching type NavigationBar t = 6.30s Find: Elements matching predicate '"Master" IN identifiers' t = 6.31s Find: Descendants matching type Button t = 6.31s Find: Elements matching predicate '"Add" IN identifiers' t = 6.41s Wait for net.hoge2.XCUITests-Example to idle t = 6.46s Synthesize event t = 6.59s Wait for net.hoge2.XCUITests-Example to idle t = 7.08s Tap "Add" Button t = 7.08s Wait for net.hoge2.XCUITests-Example to idle t = 7.12s Find the "Add" Button t = 7.13s Snapshot accessibility hierarchy for app with pid 39901 t = 7.15s Find: Descendants matching type NavigationBar t = 7.15s Find: Elements matching predicate '"Master" IN identifiers' t = 7.16s Find: Descendants matching type Button t = 7.16s Find: Elements matching predicate '"Add" IN identifiers' t = 7.26s Wait for net.hoge2.XCUITests-Example to idle t = 7.31s Synthesize event t = 7.43s Wait for net.hoge2.XCUITests-Example to idle t = 7.90s Tap Cell t = 7.90s Wait for net.hoge2.XCUITests-Example to idle t = 7.95s Find the Cell t = 7.95s Snapshot accessibility hierarchy for app with pid 39901 t = 7.98s Find: Descendants matching type Table t = 7.98s Find: Descendants matching type Cell t = 7.98s Find: Element at index 0 t = 8.08s Wait for net.hoge2.XCUITests-Example to idle t = 8.13s Synthesize event t = 8.26s Wait for net.hoge2.XCUITests-Example to idle t = 8.79s Tap "Master" Button t = 8.79s Wait for net.hoge2.XCUITests-Example to idle t = 8.85s Find the "Master" Button t = 8.85s Snapshot accessibility hierarchy for app with pid 39901 t = 8.87s Find: Descendants matching type NavigationBar t = 8.87s Find: Elements matching predicate '"Detail" IN identifiers' t = 8.87s Find: Descendants matching type Button t = 8.87s Find: Elements matching predicate '"Master" IN identifiers' t = 8.98s Wait for net.hoge2.XCUITests-Example to idle t = 9.03s Synthesize event t = 9.15s Wait for net.hoge2.XCUITests-Example to idle t = 9.67s Tap Cell t = 9.67s Wait for net.hoge2.XCUITests-Example to idle t = 9.73s Find the Cell t = 9.73s Snapshot accessibility hierarchy for app with pid 39901 t = 9.75s Find: Descendants matching type Table t = 9.75s Find: Descendants matching type Cell t = 9.75s Find: Element at index 1 t = 9.86s Wait for net.hoge2.XCUITests-Example to idle t = 9.91s Synthesize event t = 10.03s Wait for net.hoge2.XCUITests-Example to idle t = 10.56s Tap "Master" Button t = 10.56s Wait for net.hoge2.XCUITests-Example to idle t = 10.62s Find the "Master" Button t = 10.62s Snapshot accessibility hierarchy for app with pid 39901 t = 10.64s Find: Descendants matching type NavigationBar t = 10.64s Find: Elements matching predicate '"Detail" IN identifiers' t = 10.64s Find: Descendants matching type Button t = 10.64s Find: Elements matching predicate '"Master" IN identifiers' t = 10.75s Wait for net.hoge2.XCUITests-Example to idle t = 10.80s Synthesize event t = 10.92s Wait for net.hoge2.XCUITests-Example to idle t = 11.44s Tap "Edit" Button t = 11.44s Wait for net.hoge2.XCUITests-Example to idle t = 11.49s Find the "Edit" Button t = 11.50s Snapshot accessibility hierarchy for app with pid 39901 t = 11.52s Find: Descendants matching type NavigationBar t = 11.52s Find: Elements matching predicate '"Master" IN identifiers' t = 11.52s Find: Descendants matching type Button t = 11.52s Find: Elements matching predicate '"Edit" IN identifiers' t = 11.63s Wait for net.hoge2.XCUITests-Example to idle t = 11.67s Synthesize event t = 11.79s Wait for net.hoge2.XCUITests-Example to idle t = 12.28s Tap "Done" Button t = 12.28s Wait for net.hoge2.XCUITests-Example to idle t = 12.33s Find the "Done" Button t = 12.33s Snapshot accessibility hierarchy for app with pid 39901 t = 12.36s Find: Descendants matching type NavigationBar t = 12.36s Find: Elements matching predicate '"Master" IN identifiers' t = 12.36s Find: Descendants matching type Button t = 12.36s Find: Elements matching predicate '"Done" IN identifiers' t = 12.47s Wait for net.hoge2.XCUITests-Example to idle t = 12.52s Synthesize event t = 12.64s Wait for net.hoge2.XCUITests-Example to idle t = 13.11s Tear Down Test Case '-[XCUITests_ExampleUITests testExample]' passed (13.316 seconds). Test Suite 'XCUITests_ExampleUITests' passed at 2018-05-17 07:07:54.010. Test Suite 'XCUITests_ExampleUITestsFail' started at 2018-05-17 07:07:54.011 Test Case '-[XCUITests_ExampleUITestsFail testExample]' started. t = 0.00s Start Test at 2018-05-17 07:07:54.012 t = 0.05s Set Up t = 0.15s Open net.hoge2.XCUITests-Example t = 0.19s Launch net.hoge2.XCUITests-Example t = 0.19s Terminate net.hoge2.XCUITests-Example:39901 t = 5.29s Wait for net.hoge2.XCUITests-Example to idle t = 6.45s Tap "Add" Button t = 6.45s Wait for net.hoge2.XCUITests-Example to idle t = 6.49s Find the "Add" Button t = 6.50s Snapshot accessibility hierarchy for app with pid 39907 t = 6.53s Find: Descendants matching type NavigationBar t = 6.54s Find: Elements matching predicate '"Master" IN identifiers' t = 6.54s Find: Descendants matching type Button t = 6.54s Find: Elements matching predicate '"Add" IN identifiers' t = 6.64s Wait for net.hoge2.XCUITests-Example to idle t = 6.69s Synthesize event t = 6.82s Wait for net.hoge2.XCUITests-Example to idle t = 7.30s Tap "Add" Button t = 7.30s Wait for net.hoge2.XCUITests-Example to idle t = 7.35s Find the "Add" Button t = 7.35s Snapshot accessibility hierarchy for app with pid 39907 t = 7.38s Find: Descendants matching type NavigationBar t = 7.38s Find: Elements matching predicate '"Master" IN identifiers' t = 7.38s Find: Descendants matching type Button t = 7.38s Find: Elements matching predicate '"Add" IN identifiers' t = 7.49s Wait for net.hoge2.XCUITests-Example to idle t = 7.54s Synthesize event t = 7.66s Wait for net.hoge2.XCUITests-Example to idle t = 8.13s Tap Cell t = 8.13s Wait for net.hoge2.XCUITests-Example to idle t = 8.18s Find the Cell t = 8.18s Snapshot accessibility hierarchy for app with pid 39907 t = 8.20s Find: Descendants matching type Table t = 8.20s Find: Descendants matching type Cell t = 8.21s Find: Element at index 0 t = 8.31s Wait for net.hoge2.XCUITests-Example to idle t = 8.36s Synthesize event t = 8.49s Wait for net.hoge2.XCUITests-Example to idle t = 9.02s Tap "Master" Button t = 9.02s Wait for net.hoge2.XCUITests-Example to idle t = 9.08s Find the "Master" Button t = 9.08s Snapshot accessibility hierarchy for app with pid 39907 t = 9.10s Find: Descendants matching type NavigationBar t = 9.10s Find: Elements matching predicate '"Detail" IN identifiers' t = 9.10s Find: Descendants matching type Button t = 9.10s Find: Elements matching predicate '"Master" IN identifiers' t = 9.21s Wait for net.hoge2.XCUITests-Example to idle t = 9.26s Synthesize event t = 9.38s Wait for net.hoge2.XCUITests-Example to idle t = 9.90s Tap Cell t = 9.90s Wait for net.hoge2.XCUITests-Example to idle t = 9.95s Find the Cell t = 9.95s Snapshot accessibility hierarchy for app with pid 39907 t = 9.98s Find: Descendants matching type Table t = 9.98s Find: Descendants matching type Cell t = 9.98s Find: Element at index 1 t = 10.08s Wait for net.hoge2.XCUITests-Example to idle t = 10.13s Synthesize event t = 10.26s Wait for net.hoge2.XCUITests-Example to idle t = 10.78s Tap "Master" Button t = 10.78s Wait for net.hoge2.XCUITests-Example to idle t = 10.83s Find the "Master" Button t = 10.83s Snapshot accessibility hierarchy for app with pid 39907 t = 10.85s Find: Descendants matching type NavigationBar t = 10.85s Find: Elements matching predicate '"Detail" IN identifiers' t = 10.85s Find: Descendants matching type Button t = 10.85s Find: Elements matching predicate '"Master" IN identifiers' t = 10.96s Wait for net.hoge2.XCUITests-Example to idle t = 11.01s Synthesize event t = 11.12s Wait for net.hoge2.XCUITests-Example to idle t = 11.64s Tap "Edit" Button t = 11.64s Wait for net.hoge2.XCUITests-Example to idle t = 11.69s Find the "Edit" Button t = 11.69s Snapshot accessibility hierarchy for app with pid 39907 t = 11.71s Find: Descendants matching type NavigationBar t = 11.71s Find: Elements matching predicate '"Master" IN identifiers' t = 11.72s Find: Descendants matching type Button t = 11.72s Find: Elements matching predicate '"Edit" IN identifiers' t = 11.82s Wait for net.hoge2.XCUITests-Example to idle t = 11.87s Synthesize event t = 11.99s Wait for net.hoge2.XCUITests-Example to idle t = 12.47s Tap Cell t = 12.47s Wait for net.hoge2.XCUITests-Example to idle t = 12.52s Find the Cell t = 12.52s Snapshot accessibility hierarchy for app with pid 39907 t = 12.54s Find: Descendants matching type Table t = 12.54s Find: Descendants matching type Cell t = 12.54s Find: Element at index 0 t = 12.65s Wait for net.hoge2.XCUITests-Example to idle t = 12.70s Synthesize event t = 12.82s Wait for net.hoge2.XCUITests-Example to idle t = 12.87s Tap "Delete" Button t = 12.87s Wait for net.hoge2.XCUITests-Example to idle t = 12.91s Find the "Delete" Button t = 12.92s Snapshot accessibility hierarchy for app with pid 39907 t = 12.94s Find: Descendants matching type Table t = 12.94s Find: Descendants matching type Button t = 12.94s Find: Elements matching predicate '"Delete" IN identifiers' t = 13.05s Wait for net.hoge2.XCUITests-Example to idle t = 14.10s Find the "Delete" Button (retry 1) t = 14.10s Snapshot accessibility hierarchy for app with pid 39907 t = 14.12s Find: Descendants matching type Table t = 14.13s Find: Descendants matching type Button t = 14.13s Find: Elements matching predicate '"Delete" IN identifiers' t = 14.23s Wait for net.hoge2.XCUITests-Example to idle t = 15.28s Find the "Delete" Button (retry 2) t = 15.29s Snapshot accessibility hierarchy for app with pid 39907 t = 15.31s Find: Descendants matching type Table t = 15.31s Find: Descendants matching type Button t = 15.31s Find: Elements matching predicate '"Delete" IN identifiers' t = 15.42s Wait for net.hoge2.XCUITests-Example to idle ** TEST FAILED ** t = 15.56s Tear Down Test Case '-[XCUITests_ExampleUITestsFail testExample]' failed (15.769 seconds). t = 15.52s Assertion Failure: XCUITests_ExampleUITestsFail.m:57: No matches found for Find: Elements matching predicate '"Delete" IN identifiers' from input {( Test Suite 'XCUITests_ExampleUITestsFail' failed at 2018-05-17 07:08:09.782. Test Suite 'XCUITests_SubUITests' started at 2018-05-17 07:08:09.783 Test Case '-[XCUITests_SubUITests testExample]' started. t = 0.00s Start Test at 2018-05-17 07:08:09.784 t = 0.04s Set Up t = 0.14s Open net.hoge2.XCUITests-Example t = 0.18s Launch net.hoge2.XCUITests-Example t = 0.18s Terminate net.hoge2.XCUITests-Example:39907 t = 5.27s Wait for net.hoge2.XCUITests-Example to idle t = 6.46s Tap "Add" Button t = 6.46s Wait for net.hoge2.XCUITests-Example to idle t = 6.51s Find the "Add" Button t = 6.51s Snapshot accessibility hierarchy for app with pid 39915 t = 6.55s Find: Descendants matching type NavigationBar t = 6.55s Find: Elements matching predicate '"Master" IN identifiers' t = 6.55s Find: Descendants matching type Button t = 6.56s Find: Elements matching predicate '"Add" IN identifiers' t = 6.66s Wait for net.hoge2.XCUITests-Example to idle t = 6.71s Synthesize event t = 6.85s Wait for net.hoge2.XCUITests-Example to idle t = 7.33s Tap "Add" Button t = 7.33s Wait for net.hoge2.XCUITests-Example to idle t = 7.39s Find the "Add" Button t = 7.39s Snapshot accessibility hierarchy for app with pid 39915 t = 7.42s Find: Descendants matching type NavigationBar t = 7.42s Find: Elements matching predicate '"Master" IN identifiers' t = 7.42s Find: Descendants matching type Button t = 7.42s Find: Elements matching predicate '"Add" IN identifiers' t = 7.53s Wait for net.hoge2.XCUITests-Example to idle t = 7.57s Synthesize event t = 7.69s Wait for net.hoge2.XCUITests-Example to idle t = 8.17s Tap Cell t = 8.17s Wait for net.hoge2.XCUITests-Example to idle t = 8.22s Find the Cell t = 8.22s Snapshot accessibility hierarchy for app with pid 39915 t = 8.24s Find: Descendants matching type Table t = 8.24s Find: Descendants matching type Cell t = 8.24s Find: Element at index 0 t = 8.35s Wait for net.hoge2.XCUITests-Example to idle t = 8.40s Synthesize event t = 8.52s Wait for net.hoge2.XCUITests-Example to idle t = 9.06s Tap "Master" Button t = 9.06s Wait for net.hoge2.XCUITests-Example to idle t = 9.12s Find the "Master" Button t = 9.12s Snapshot accessibility hierarchy for app with pid 39915 t = 9.15s Find: Descendants matching type NavigationBar t = 9.15s Find: Elements matching predicate '"Detail" IN identifiers' t = 9.15s Find: Descendants matching type Button t = 9.15s Find: Elements matching predicate '"Master" IN identifiers' t = 9.26s Wait for net.hoge2.XCUITests-Example to idle t = 9.31s Synthesize event t = 9.44s Wait for net.hoge2.XCUITests-Example to idle t = 9.95s Tap Cell t = 9.95s Wait for net.hoge2.XCUITests-Example to idle t = 10.01s Find the Cell t = 10.01s Snapshot accessibility hierarchy for app with pid 39915 t = 10.03s Find: Descendants matching type Table t = 10.04s Find: Descendants matching type Cell t = 10.04s Find: Element at index 1 t = 10.14s Wait for net.hoge2.XCUITests-Example to idle t = 10.20s Synthesize event t = 10.33s Wait for net.hoge2.XCUITests-Example to idle t = 10.85s Tap "Master" Button t = 10.85s Wait for net.hoge2.XCUITests-Example to idle t = 10.90s Find the "Master" Button t = 10.90s Snapshot accessibility hierarchy for app with pid 39915 t = 10.92s Find: Descendants matching type NavigationBar t = 10.93s Find: Elements matching predicate '"Detail" IN identifiers' t = 10.93s Find: Descendants matching type Button t = 10.93s Find: Elements matching predicate '"Master" IN identifiers' t = 11.04s Wait for net.hoge2.XCUITests-Example to idle t = 11.09s Synthesize event t = 11.21s Wait for net.hoge2.XCUITests-Example to idle t = 11.72s Tap "Edit" Button t = 11.72s Wait for net.hoge2.XCUITests-Example to idle t = 11.78s Find the "Edit" Button t = 11.78s Snapshot accessibility hierarchy for app with pid 39915 t = 11.81s Find: Descendants matching type NavigationBar t = 11.81s Find: Elements matching predicate '"Master" IN identifiers' t = 11.81s Find: Descendants matching type Button t = 11.81s Find: Elements matching predicate '"Edit" IN identifiers' t = 11.91s Wait for net.hoge2.XCUITests-Example to idle t = 11.96s Synthesize event t = 12.08s Wait for net.hoge2.XCUITests-Example to idle t = 12.56s Tap "Done" Button t = 12.56s Wait for net.hoge2.XCUITests-Example to idle t = 12.62s Find the "Done" Button t = 12.62s Snapshot accessibility hierarchy for app with pid 39915 t = 12.65s Find: Descendants matching type NavigationBar t = 12.65s Find: Elements matching predicate '"Master" IN identifiers' t = 12.65s Find: Descendants matching type Button t = 12.65s Find: Elements matching predicate '"Done" IN identifiers' t = 12.76s Wait for net.hoge2.XCUITests-Example to idle t = 12.81s Synthesize event t = 12.93s Wait for net.hoge2.XCUITests-Example to idle t = 13.41s Tear Down Test Case '-[XCUITests_SubUITests testExample]' passed (13.610 seconds). Test Suite 'XCUITests-ExampleUITests.xctest' failed at 2018-05-17 07:08:23.395. Test Suite 'XCUITests_SubUITests' passed at 2018-05-17 07:08:23.394. t = 15.52s Assertion Failure: XCUITests_ExampleUITestsFail.m:57: No matches found for Find: Elements matching predicate '"Delete" IN identifiers' from input {( Test Suite 'All tests' failed at 2018-05-17 07:08:23.396. ================================================ FILE: src/test/resources/XCTest_output_crashing_1.txt ================================================ === BUILD TARGET Pods-MatrixSDK-Mantle OF PROJECT Pods WITH CONFIGURATION Debug === Check dependencies === BUILD TARGET Pods-MatrixSDK-AFNetworking OF PROJECT Pods WITH CONFIGURATION Debug === Check dependencies === BUILD TARGET Pods-MatrixSDK OF PROJECT Pods WITH CONFIGURATION Debug === Check dependencies === BUILD TARGET MatrixSDK OF PROJECT MatrixSDK WITH CONFIGURATION Debug === Check dependencies PhaseScriptExecution Check\ Pods\ Manifest.lock /Users/davidjb/Library/Developer/Xcode/DerivedData/MatrixSDK-fxluueiwaovpfwffbxfypleqfrnl/Build/Intermediates/MatrixSDK.build/Debug-iphonesimulator/MatrixSDK.build/Script-977E3F228F61BF8765F90684.sh cd /Users/davidjb/matrix/matrix-ios-sdk/sdk /bin/sh -c /Users/davidjb/Library/Developer/Xcode/DerivedData/MatrixSDK-fxluueiwaovpfwffbxfypleqfrnl/Build/Intermediates/MatrixSDK.build/Debug-iphonesimulator/MatrixSDK.build/Script-977E3F228F61BF8765F90684.sh PhaseScriptExecution Copy\ Pods\ Resources /Users/davidjb/Library/Developer/Xcode/DerivedData/MatrixSDK-fxluueiwaovpfwffbxfypleqfrnl/Build/Intermediates/MatrixSDK.build/Debug-iphonesimulator/MatrixSDK.build/Script-FDD4B60A568A908CBDAC1A26.sh cd /Users/davidjb/matrix/matrix-ios-sdk/sdk /bin/sh -c /Users/davidjb/Library/Developer/Xcode/DerivedData/MatrixSDK-fxluueiwaovpfwffbxfypleqfrnl/Build/Intermediates/MatrixSDK.build/Debug-iphonesimulator/MatrixSDK.build/Script-FDD4B60A568A908CBDAC1A26.sh building file list ... done sent 29 bytes received 20 bytes 98.00 bytes/sec total size is 0 speedup is 0.00 === BUILD TARGET MatrixSDKTests OF PROJECT MatrixSDK WITH CONFIGURATION Debug === Check dependencies Test Suite 'All tests' started at 2014-12-15 17:55:06 +0000 Test Suite 'MatrixSDKTests.xctest' started at 2014-12-15 17:55:06 +0000 Test Suite 'MXErrorTests' started at 2014-12-15 17:55:06 +0000 Test Case '-[MXErrorTests testInit]' started. Test Case '-[MXErrorTests testInit]' passed (0.031 seconds). Test Case '-[MXErrorTests testNonMatrixNSError]' started. Test Case '-[MXErrorTests testNonMatrixNSError]' passed (0.000 seconds). Test Case '-[MXErrorTests testNSError]' started. Test Case '-[MXErrorTests testNSError]' passed (0.000 seconds). Test Suite 'MXErrorTests' passed at 2014-12-15 17:55:06 +0000. Executed 3 tests, with 0 failures (0 unexpected) in 0.032 (0.033) seconds Test Suite 'MXEventTests' started at 2014-12-15 17:55:06 +0000 Test Case '-[MXEventTests testIsState]' started. 2014-12-15 17:55:06.800 xctest[2422:5067215] Request failed for path: register - HTTP code: 0 2014-12-15 17:55:06.800 xctest[2422:5067215] *** Assertion failure in -[MatrixSDKTestsData getBobCredentials:], /Users/davidjb/matrix/matrix-ios-sdk/sdk/MatrixSDKTests/MatrixSDKTestsData.m:109 2014-12-15 17:55:06.810 xctest[2422:5067215] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot create mxBOB account' *** First throw call stack: ( 0 CoreFoundation 0x00883946 __exceptionPreprocess + 182 1 libobjc.A.dylib 0x0050ca97 objc_exception_throw + 44 2 CoreFoundation 0x008837da +[NSException raise:format:arguments:] + 138 3 Foundation 0x00180810 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 118 4 MatrixSDKTests 0x0357de1c __40-[MatrixSDKTestsData getBobCredentials:]_block_invoke19 + 892 5 MatrixSDK 0x0376d974 __73-[MXRestClient registerOrLoginWithUser:user:andPassword:success:failure:]_block_invoke57 + 84 6 MatrixSDK 0x0375f51e __87-[MXHTTPClient requestWithMethod:path:parameters:data:headers:timeout:success:failure:]_block_invoke68 + 862 7 MatrixSDK 0x037798b1 __64-[AFHTTPRequestOperation setCompletionBlockWithSuccess:failure:]_block_invoke_3 + 97 8 libdispatch.dylib 0x019bfa2a _dispatch_call_block_and_release + 15 9 libdispatch.dylib 0x019dc03f _dispatch_client_callout + 14 10 libdispatch.dylib 0x019c5764 _dispatch_main_queue_callback_4CF + 470 11 CoreFoundation 0x007dd95e __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14 12 CoreFoundation 0x0079c760 __CFRunLoopRun + 2256 13 CoreFoundation 0x0079bbcb CFRunLoopRunSpecific + 443 14 CoreFoundation 0x0079b9fb CFRunLoopRunInMode + 123 15 Foundation 0x00113d98 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 309 16 XCTest 0x20119a31 -[XCTestCase(AsynchronousTesting) waitForExpectationsWithTimeout:handler:] + 1192 17 MatrixSDKTests 0x0357e70b -[MatrixSDKTestsData doMXRestClientTestWithBob:readyToTest:] + 427 18 MatrixSDKTests 0x0357ed85 -[MatrixSDKTestsData doMXRestClientTestWithBobAndARoom:readyToTest:] + 245 19 MatrixSDKTests 0x03581e7f -[MatrixSDKTestsData doMXRestClientTestWithBobAndARoomWithMessages:readyToTest:] + 239 20 MatrixSDKTests 0x035e2c83 -[MXEventTests testIsState] + 179 21 CoreFoundation 0x0076676d __invoking___ + 29 22 CoreFoundation 0x00766618 -[NSInvocation invoke] + 360 23 XCTest 0x2010897b -[XCTestCase invokeTest] + 320 24 XCTest 0x20108bb9 -[XCTestCase performTest:] + 184 25 XCTest 0x20114162 -[XCTest run] + 314 26 XCTest 0x20107598 -[XCTestSuite performTest:] + 406 27 XCTest 0x20114162 -[XCTest run] + 314 28 XCTest 0x20107598 -[XCTestSuite performTest:] + 406 29 XCTest 0x20114162 -[XCTest run] + 314 30 XCTest 0x20107598 -[XCTestSuite performTest:] + 406 31 XCTest 0x20114162 -[XCTest run] + 314 32 XCTest 0x20103de2 __25-[XCTestDriver _runSuite]_block_invoke + 61 33 XCTest 0x20110c82 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 184 34 XCTest 0x20103d06 -[XCTestDriver _runSuite] + 285 35 XCTest 0x20104951 -[XCTestDriver _checkForTestManager] + 272 36 XCTest 0x20104c6b -[XCTestDriver runTestSuite:completionHandler:] + 378 37 XCTest 0x2011775c +[XCTestProbe runTests:] + 216 38 libobjc.A.dylib 0x0052267e +[NSObject performSelector:withObject:] + 70 39 xctest 0x00046237 xctest + 4663 40 xctest 0x000464ac xctest + 5292 41 xctest 0x0004658f xctest + 5519 42 xctest 0x00045e3d xctest + 3645 43 libdyld.dylib 0x01a02ac9 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException ================================================ FILE: src/test/resources/XCTest_output_failing_1.txt ================================================ Test Suite 'All tests' started at 2014-12-12 05:02:01 +0000 Test Suite 'UnitTestsCardExampleTests.xctest' started at 2014-12-12 05:02:01 +0000 Test Suite 'CardTestCase' started at 2014-12-12 05:02:01 +0000 Test Case '-[CardTestCase testDoesNotMatchDifferentCard]' started. Test Case '-[CardTestCase testDoesNotMatchDifferentCard]' passed (0.000 seconds). Test Case '-[CardTestCase testMatchesDifferentCardWithSameContents]' started. Test Case '-[CardTestCase testMatchesDifferentCardWithSameContents]' passed (0.000 seconds). Test Case '-[CardTestCase testMatchesForAtLeastOneCard]' started. Test Case '-[CardTestCase testMatchesForAtLeastOneCard]' passed (0.000 seconds). Test Suite 'CardTestCase' passed at 2014-12-12 05:02:01 +0000. Executed 3 tests, with 0 failures (0 unexpected) in 0.001 (0.003) seconds Test Suite 'DeckTestCase' started at 2014-12-12 05:02:01 +0000 Test Case '-[DeckTestCase testDeckWithMultipleCardsWillRandomlyDrawThemAll]' started. Test Case '-[DeckTestCase testDeckWithMultipleCardsWillRandomlyDrawThemAll]' passed (0.001 seconds). Test Case '-[DeckTestCase testDrawCardFromEmptyDeckAnswersNoCard]' started. Test Case '-[DeckTestCase testDrawCardFromEmptyDeckAnswersNoCard]' passed (0.000 seconds). Test Case '-[DeckTestCase testDrawnRandomCardsAreDifferent]' started. Test Case '-[DeckTestCase testDrawnRandomCardsAreDifferent]' passed (0.000 seconds). Test Case '-[DeckTestCase testOneCardDeckShouldAnswerThatCard]' started. Test Case '-[DeckTestCase testOneCardDeckShouldAnswerThatCard]' passed (0.000 seconds). Test Suite 'DeckTestCase' passed at 2014-12-12 05:02:01 +0000. Executed 4 tests, with 0 failures (0 unexpected) in 0.002 (0.013) seconds Test Suite 'PlayingCardDeckTestCase' started at 2014-12-12 05:02:01 +0000 Test Case '-[PlayingCardDeckTestCase testPlayingCardDeckAnswersPlayingCards]' started. Test Case '-[PlayingCardDeckTestCase testPlayingCardDeckAnswersPlayingCards]' passed (0.001 seconds). Test Case '-[PlayingCardDeckTestCase testPlayingCardDeckHasTheCorrectInitialCards]' started. Test Case '-[PlayingCardDeckTestCase testPlayingCardDeckHasTheCorrectInitialCards]' passed (0.001 seconds). Test Suite 'PlayingCardDeckTestCase' passed at 2014-12-12 05:02:01 +0000. Executed 2 tests, with 0 failures (0 unexpected) in 0.001 (0.002) seconds Test Suite 'PlayingCardTestCase' started at 2014-12-12 05:02:01 +0000 Test Case '-[PlayingCardTestCase testSetSuitAnyValidAccepted]' started. Test Case '-[PlayingCardTestCase testSetSuitAnyValidAccepted]' passed (0.000 seconds). Test Case '-[PlayingCardTestCase testSetSuitInvalidRejected]' started. Test Case '-[PlayingCardTestCase testSetSuitInvalidRejected]' passed (0.000 seconds). Test Case '-[PlayingCardTestCase testTheValidSuits]' started. /Users/lacostej/Code/Jenkins/xcode-plugin/examples/UnitTestsCardExample/UnitTestsCardExampleTests/PlayingCardTestCase.m:34: error: -[PlayingCardTestCase testTheValidSuits] : ((howMany) equal to (3)) failed: ("4") is not equal to ("3") - Should be only 4 Test Case '-[PlayingCardTestCase testTheValidSuits]' failed (0.001 seconds). Test Suite 'PlayingCardTestCase' failed at 2014-12-12 05:02:01 +0000. Executed 3 tests, with 1 failure (0 unexpected) in 0.002 (0.003) seconds Test Suite 'UnitTestsCardExampleTests.xctest' failed at 2014-12-12 05:02:01 +0000. Executed 12 tests, with 1 failure (0 unexpected) in 0.006 (0.024) seconds Test Suite 'All tests' failed at 2014-12-12 05:02:01 +0000. Executed 12 tests, with 1 failure (0 unexpected) in 0.006 (0.026) seconds Failing tests: -[PlayingCardTestCase testTheValidSuits] ** TEST FAILED ** ================================================ FILE: src/test/resources/XCTest_output_failing_2.txt ================================================ Test Suite 'All tests' started at 2015-01-05 18:41:39 +0000 Test Suite 'OMPlus-DemoTests.xctest' started at 2015-01-05 18:41:39 +0000 Test Suite 'OMCOffsetRangeClosedOpenTests' started at 2015-01-05 18:41:39 +0000 Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testContainsClosedOpenShouldContainStart]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testContainsClosedOpenShouldContainStart]' passed (0.008 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testContainsClosedOpenShouldNotContainEnd]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testContainsClosedOpenShouldNotContainEnd]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testContainsClosedOpenShouldNotContainValueGreaterThanEnd]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testContainsClosedOpenShouldNotContainValueGreaterThanEnd]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testContainsClosedOpenShouldNotContainValueLesserThanStart]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testContainsClosedOpenShouldNotContainValueLesserThanStart]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldContainRange]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldContainRange]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldContainRangeEndingOnEnd]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldContainRangeEndingOnEnd]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldIntersectOtherRangeContainingEnd]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldIntersectOtherRangeContainingEnd]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldIntersectOtherRangeContainingEntireRange]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldIntersectOtherRangeContainingEntireRange]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldIntersectOtherRangeContainingStart]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldIntersectOtherRangeContainingStart]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldNotIntersectOtherRangeEndingOnStart]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldNotIntersectOtherRangeEndingOnStart]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldNotIntersectOtherRangeStartingOnEnd]' started. Test Case '-[OMPlus_DemoTests.OMCOffsetRangeClosedOpenTests testShouldNotIntersectOtherRangeStartingOnEnd]' passed (0.002 seconds). Test Suite 'OMCOffsetRangeClosedOpenTests' passed at 2015-01-05 18:41:39 +0000. Executed 11 tests, with 0 failures (0 unexpected) in 0.012 (0.037) seconds Test Suite 'OMDPacketSpecificationTest' started at 2015-01-05 18:41:39 +0000 Test Case '-[OMPlus_DemoTests.OMDPacketSpecificationTest testFindsMultipleIssues]' started. Test Case '-[OMPlus_DemoTests.OMDPacketSpecificationTest testFindsMultipleIssues]' passed (0.011 seconds). Test Suite 'OMDPacketSpecificationTest' passed at 2015-01-05 18:41:39 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.011 (0.012) seconds Test Suite 'OMSAccountRegistrationTests' started at 2015-01-05 18:41:39 +0000 Test Case '-[OMPlus_DemoTests.OMSAccountRegistrationTests testShouldRegisterAnAccount]' started. Test Case '-[OMPlus_DemoTests.OMSAccountRegistrationTests testShouldRegisterAnAccount]' passed (0.065 seconds). Test Case '-[OMPlus_DemoTests.OMSAccountRegistrationTests testShouldUpdateExistingAccount]' started. Test Case '-[OMPlus_DemoTests.OMSAccountRegistrationTests testShouldUpdateExistingAccount]' passed (0.012 seconds). Test Suite 'OMSAccountRegistrationTests' passed at 2015-01-05 18:41:39 +0000. Executed 2 tests, with 0 failures (0 unexpected) in 0.077 (0.078) seconds Test Suite 'OMSCappedTimeSeriesTests' started at 2015-01-05 18:41:39 +0000 Test Case '-[OMPlus_DemoTests.OMSCappedTimeSeriesTests testClearing]' started. Test Case '-[OMPlus_DemoTests.OMSCappedTimeSeriesTests testClearing]' passed (0.008 seconds). Test Suite 'OMSCappedTimeSeriesTests' passed at 2015-01-05 18:41:39 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.008 (0.011) seconds Test Suite 'OMSCoreEventPushingQueueStrategyTests' started at 2015-01-05 18:41:39 +0000 Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testRemainingCountShouldAddItemsFromTheThreeQueues]' started. Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testRemainingCountShouldAddItemsFromTheThreeQueues]' passed (1.925 seconds). Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testRemainingCountShouldCountSinceLastAcknowledgement]' started. Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testRemainingCountShouldCountSinceLastAcknowledgement]' passed (0.628 seconds). Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testShouldFetch6000BoxSyncEventsAnd1000BoxLiveEventsAnd500SdkEvents]' started. Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testShouldFetch6000BoxSyncEventsAnd1000BoxLiveEventsAnd500SdkEvents]' passed (1.245 seconds). Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testShouldFetch6000BoxSyncEventsAnd1500BoxLiveEvents]' started. Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testShouldFetch6000BoxSyncEventsAnd1500BoxLiveEvents]' passed (2.141 seconds). Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testShouldFetch7500BoxSyncEvents]' started. Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testShouldFetch7500BoxSyncEvents]' passed (2.637 seconds). Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testShouldFetchFromLastAcknowledgement]' started. Test Case '-[OMPlus_DemoTests.OMSCoreEventPushingQueueStrategyTests testShouldFetchFromLastAcknowledgement]' passed (0.819 seconds). Test Suite 'OMSCoreEventPushingQueueStrategyTests' passed at 2015-01-05 18:41:48 +0000. Executed 6 tests, with 0 failures (0 unexpected) in 9.395 (9.398) seconds Test Suite 'OMSCredentialRegistrationTests' started at 2015-01-05 18:41:48 +0000 Test Case '-[OMPlus_DemoTests.OMSCredentialRegistrationTests testShouldNotRegisterMultipleCredentials]' started. Test Case '-[OMPlus_DemoTests.OMSCredentialRegistrationTests testShouldNotRegisterMultipleCredentials]' passed (0.023 seconds). Test Case '-[OMPlus_DemoTests.OMSCredentialRegistrationTests testShouldRegisterCredentials]' started. Test Case '-[OMPlus_DemoTests.OMSCredentialRegistrationTests testShouldRegisterCredentials]' passed (0.010 seconds). Test Case '-[OMPlus_DemoTests.OMSCredentialRegistrationTests testShouldUpdatePassword]' started. Test Case '-[OMPlus_DemoTests.OMSCredentialRegistrationTests testShouldUpdatePassword]' passed (0.014 seconds). Test Suite 'OMSCredentialRegistrationTests' passed at 2015-01-05 18:41:49 +0000. Executed 3 tests, with 0 failures (0 unexpected) in 0.047 (0.048) seconds Test Suite 'OMSDailyReportStoreTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldFindAllOrderedByDay]' started. Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldFindAllOrderedByDay]' passed (0.019 seconds). Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldRetrieveLatestLifestyleReport]' started. Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldRetrieveLatestLifestyleReport]' passed (0.024 seconds). Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldRetrieveLifestyleReportByDay]' started. Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldRetrieveLifestyleReportByDay]' passed (0.016 seconds). Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldRetrieveLifestyleReportsWithinTimeRange]' started. Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldRetrieveLifestyleReportsWithinTimeRange]' passed (0.022 seconds). Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldStoreLifestyleReport]' started. Test Case '-[OMPlus_DemoTests.OMSDailyReportStoreTests testShouldStoreLifestyleReport]' passed (0.016 seconds). Test Suite 'OMSDailyReportStoreTests' passed at 2015-01-05 18:41:49 +0000. Executed 5 tests, with 0 failures (0 unexpected) in 0.097 (0.099) seconds Test Suite 'OMSDoublePrimitiveTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSDoublePrimitiveTests testShouldRountDoubleToInt]' started. Test Case '-[OMPlus_DemoTests.OMSDoublePrimitiveTests testShouldRountDoubleToInt]' passed (0.001 seconds). Test Suite 'OMSDoublePrimitiveTests' passed at 2015-01-05 18:41:49 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.001 (0.001) seconds Test Suite 'OMSFitnessTestFacadeTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testHasToFinishBeforeStarting]' started. Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testHasToFinishBeforeStarting]' passed (0.014 seconds). Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testHasToStartBeforeEnding]' started. Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testHasToStartBeforeEnding]' passed (0.014 seconds). Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testHasToStartBeforeRecovery]' started. Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testHasToStartBeforeRecovery]' passed (0.013 seconds). Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testWithoutScore]' started. Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testWithoutScore]' passed (0.012 seconds). Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testWithScore]' started. Test Case '-[OMPlus_DemoTests.OMSFitnessTestFacadeTests testWithScore]' passed (0.013 seconds). Test Suite 'OMSFitnessTestFacadeTests' passed at 2015-01-05 18:41:49 +0000. Executed 5 tests, with 0 failures (0 unexpected) in 0.066 (0.068) seconds Test Suite 'OMSGoalsProjectorTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testAddTimeInHrZoneGoal]' started. Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testAddTimeInHrZoneGoal]' passed (0.015 seconds). Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testPerformanceExample]' started. :0: Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testPerformanceExample]' measured [Time, seconds] average: 0.000, relative standard deviation: 114.408%, values: [0.000005, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001, 0.000001], performanceMetricID:com.apple.XCTPerformanceMetric_WallClockTime, baselineName: "", baselineAverage: , maxPercentRegression: 10.000%, maxPercentRelativeStandardDeviation: 10.000%, maxRegression: 0.100, maxStandardDeviation: 0.100 Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testPerformanceExample]' passed (0.275 seconds). Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testRemoveTimeInHrZoneGoal]' started. Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testRemoveTimeInHrZoneGoal]' passed (0.012 seconds). Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testUpdateTimeInHrZoneGoal]' started. Test Case '-[OMPlus_DemoTests.OMSGoalsProjectorTests testUpdateTimeInHrZoneGoal]' passed (0.013 seconds). Test Suite 'OMSGoalsProjectorTests' passed at 2015-01-05 18:41:49 +0000. Executed 4 tests, with 0 failures (0 unexpected) in 0.316 (0.318) seconds Test Suite 'OMSHeightUnitsConverterTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSHeightUnitsConverterTests testShouldMapToInternationalMetric]' started. Test Case '-[OMPlus_DemoTests.OMSHeightUnitsConverterTests testShouldMapToInternationalMetric]' passed (0.000 seconds). Test Suite 'OMSHeightUnitsConverterTests' passed at 2015-01-05 18:41:49 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.000 (0.001) seconds Test Suite 'OMSKafkaConsumersTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testFivePersistentElementsShouldBeLeftToConsumeWhenConsumingPersistentMessages]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testFivePersistentElementsShouldBeLeftToConsumeWhenConsumingPersistentMessages]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testFivePersistentElementsShouldBeLeftToConsumeWhenConsumingTransientMessages]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testFivePersistentElementsShouldBeLeftToConsumeWhenConsumingTransientMessages]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testFiveTransientElementsShouldBeLeftToConsumeWhenConsumingTransientMessages]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testFiveTransientElementsShouldBeLeftToConsumeWhenConsumingTransientMessages]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testNoTransientElementsShouldBeLeftToConsumeWhenConsumingPersistentMessagesOnly]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testNoTransientElementsShouldBeLeftToConsumeWhenConsumingPersistentMessagesOnly]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testSixPersistentElementsShouldBeLeftToConsumeWhenConsumingTransientMessagesUsingNilClientOffset]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testSixPersistentElementsShouldBeLeftToConsumeWhenConsumingTransientMessagesUsingNilClientOffset]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testSixTransientElementsShouldBeLeftToConsumeWhenConsumingTransientMessagesUsingNilClientOffset]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testSixTransientElementsShouldBeLeftToConsumeWhenConsumingTransientMessagesUsingNilClientOffset]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testZeroElementsShouldBeLeftToConsumeWhenTopicOffsetIsNil]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testZeroElementsShouldBeLeftToConsumeWhenTopicOffsetIsNil]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testZeroElementsShouldBeLeftToConsumeWhenTopicPersistentOffsetIsNil]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaConsumersTests testZeroElementsShouldBeLeftToConsumeWhenTopicPersistentOffsetIsNil]' passed (0.000 seconds). Test Suite 'OMSKafkaConsumersTests' passed at 2015-01-05 18:41:49 +0000. Executed 8 tests, with 0 failures (0 unexpected) in 0.002 (0.008) seconds Test Suite 'OMSKafkaEventuallyPersistentQueueTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testEmptyQueueShouldNotHaveAnyNewestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testEmptyQueueShouldNotHaveAnyNewestMessage]' passed (0.043 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testEmptyQueueShouldNotHaveAnyNewestPersistedMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testEmptyQueueShouldNotHaveAnyNewestPersistedMessage]' passed (0.018 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testEmptyQueueShouldNotHaveAnyOldestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testEmptyQueueShouldNotHaveAnyOldestMessage]' passed (0.019 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldFetchAndMergeResultsFromPersistentAndTransientQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldFetchAndMergeResultsFromPersistentAndTransientQueue]' passed (0.025 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldFetchFromTransientQueueFromOffset0WithoutAnyMessageAlreadyPersisted]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldFetchFromTransientQueueFromOffset0WithoutAnyMessageAlreadyPersisted]' passed (0.016 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldFetchFromTransientQueueFromOffset1WithoutAnyMessageAlreadyPersisted]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldFetchFromTransientQueueFromOffset1WithoutAnyMessageAlreadyPersisted]' passed (0.017 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldFlushTransientQueueWhenRequested]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldFlushTransientQueueWhenRequested]' passed (0.018 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldNotFetchDeletedItemsFromTransientAndPersistentQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldNotFetchDeletedItemsFromTransientAndPersistentQueue]' passed (0.022 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldReturnNewestMessageFromTransientQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldReturnNewestMessageFromTransientQueue]' passed (0.020 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldReturnNewestPersistedMessageFromTransientQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldReturnNewestPersistedMessageFromTransientQueue]' passed (0.020 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldReturnOldestMessageFromPersistentTransientQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldReturnOldestMessageFromPersistentTransientQueue]' passed (0.021 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldReturnOldestMessageFromTransientQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShouldReturnOldestMessageFromTransientQueue]' passed (0.019 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShoulOnlyPersistOnThirdMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaEventuallyPersistentQueueTests testShoulOnlyPersistOnThirdMessage]' passed (0.019 seconds). Test Suite 'OMSKafkaEventuallyPersistentQueueTests' passed at 2015-01-05 18:41:49 +0000. Executed 13 tests, with 0 failures (0 unexpected) in 0.276 (0.282) seconds Test Suite 'OMSKafkaGarbageCollectorTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaGarbageCollectorTests testGCDoesntDeleteWhenNotConsumed]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaGarbageCollectorTests testGCDoesntDeleteWhenNotConsumed]' passed (0.026 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaGarbageCollectorTests testGCHandleNilOffsetSoItAvoidDeletingUnconsumedElements]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaGarbageCollectorTests testGCHandleNilOffsetSoItAvoidDeletingUnconsumedElements]' passed (0.024 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaGarbageCollectorTests testGCKeepsOnlyOneElementInTheQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaGarbageCollectorTests testGCKeepsOnlyOneElementInTheQueue]' passed (0.026 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaGarbageCollectorTests testGCWaitsForSlowestConsumer]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaGarbageCollectorTests testGCWaitsForSlowestConsumer]' passed (0.026 seconds). Test Suite 'OMSKafkaGarbageCollectorTests' passed at 2015-01-05 18:41:49 +0000. Executed 4 tests, with 0 failures (0 unexpected) in 0.102 (0.112) seconds Test Suite 'OMSKafkaMessageIndexTests' started at 2015-01-05 18:41:49 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testEmptyIndexShouldNotReturnAnyLogicalOffsetRange]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testEmptyIndexShouldNotReturnAnyLogicalOffsetRange]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testEmptyIndexShouldNotReturnAnyLogicalOffsetRangeAssociatedWithPhysicalRange]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testEmptyIndexShouldNotReturnAnyLogicalOffsetRangeAssociatedWithPhysicalRange]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testEmptyIndexShouldNotReturnAnyPhysicalOffset]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testEmptyIndexShouldNotReturnAnyPhysicalOffset]' passed (0.021 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testIndexShouldNotReturnAnyLogicalOffsetRangeAssociatedWithNonExistingPhysicalRange]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testIndexShouldNotReturnAnyLogicalOffsetRangeAssociatedWithNonExistingPhysicalRange]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testIndexShouldReturnLogicalOffsetRangeAssociatedWithExistingPhysicalRange]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testIndexShouldReturnLogicalOffsetRangeAssociatedWithExistingPhysicalRange]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testIndexWithOneRangeShouldReturnIt]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testIndexWithOneRangeShouldReturnIt]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testIndexWithSeveralRangesShouldMergeThem]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testIndexWithSeveralRangesShouldMergeThem]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testPruneShouldHaveClosedOpenSemantics]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testPruneShouldHaveClosedOpenSemantics]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldNotReturnAnyPhysicalOffsetContainingLogicalOffsetOutsideOfInterval]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldNotReturnAnyPhysicalOffsetContainingLogicalOffsetOutsideOfInterval]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldNotReturnPysicalOffsetRangeWhenNoIntersectionBetweenIndexAndQuery]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldNotReturnPysicalOffsetRangeWhenNoIntersectionBetweenIndexAndQuery]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldPruneOldMappingsAndKeepNewOnes]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldPruneOldMappingsAndKeepNewOnes]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldRestoreEmptyState]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldRestoreEmptyState]' passed (0.003 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldRestoreState]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldRestoreState]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnNilPhysicalOffsetRange]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnNilPhysicalOffsetRange]' passed (0.007 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPhysicalOffsetContainingLogicalOffset]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPhysicalOffsetContainingLogicalOffset]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPhysicalOffsetRangeOf1Element]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPhysicalOffsetRangeOf1Element]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPhysicalOffsetRangeOf3Elements]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPhysicalOffsetRangeOf3Elements]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPysicalOffsetRangeAssociatedWithLogicalOffsetFullyContainedInIndex]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPysicalOffsetRangeAssociatedWithLogicalOffsetFullyContainedInIndex]' passed (0.015 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPysicalOffsetRangeAssociatedWithLogicalOffsetIntersectingEnd]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPysicalOffsetRangeAssociatedWithLogicalOffsetIntersectingEnd]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPysicalOffsetRangeAssociatedWithLogicalOffsetIntersectingStart]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPysicalOffsetRangeAssociatedWithLogicalOffsetIntersectingStart]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPysicalOffsetRangeWhenThereAreGaps]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaMessageIndexTests testShouldReturnPysicalOffsetRangeWhenThereAreGaps]' passed (0.000 seconds). Test Suite 'OMSKafkaMessageIndexTests' passed at 2015-01-05 18:41:50 +0000. Executed 21 tests, with 0 failures (0 unexpected) in 0.051 (0.107) seconds Test Suite 'OMSKafkaPersistentQueueTests' started at 2015-01-05 18:41:50 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testCreatedMessageIndexShouldBeDirty]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testCreatedMessageIndexShouldBeDirty]' passed (0.025 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testCreatedMessageIndexShouldNotBeDirty]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testCreatedMessageIndexShouldNotBeDirty]' passed (0.021 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testEmptyQueueShouldNotReturnNewestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testEmptyQueueShouldNotReturnNewestMessage]' passed (0.016 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testEmptyQueueShouldNotReturnOldestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testEmptyQueueShouldNotReturnOldestMessage]' passed (0.016 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testNonEmptyQueueShouldReturnNewestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testNonEmptyQueueShouldReturnNewestMessage]' passed (0.020 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testNonEmptyQueueShouldReturnOldestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testNonEmptyQueueShouldReturnOldestMessage]' passed (0.020 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testPersistingEmptyArrayShouldNotChangeTheCount]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testPersistingEmptyArrayShouldNotChangeTheCount]' passed (0.017 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testPersistingEmptyArrayShouldNotLeadToWeirdErrors]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testPersistingEmptyArrayShouldNotLeadToWeirdErrors]' passed (0.017 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldCreateIndex]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldCreateIndex]' passed (0.024 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldDeleteMessagesUntilGivenOffsetAtBeginningOfNextBucket]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldDeleteMessagesUntilGivenOffsetAtBeginningOfNextBucket]' passed (0.026 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldDeleteMessagesUntilGivenOffsetInTheMiddleOfBucket]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldDeleteMessagesUntilGivenOffsetInTheMiddleOfBucket]' passed (0.028 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchAllElementsFromGivenBucket]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchAllElementsFromGivenBucket]' passed (0.022 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchElementsSpanningThreeBuckets]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchElementsSpanningThreeBuckets]' passed (0.030 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchElementsSpanningTwoBuckets]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchElementsSpanningTwoBuckets]' passed (0.022 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchMaxWithHoles]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchMaxWithHoles]' passed (0.021 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchSomeElementsOfGivenBucket]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldFetchSomeElementsOfGivenBucket]' passed (0.020 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldHandleHolesInBuckets]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldHandleHolesInBuckets]' passed (0.026 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldNotDoAnythingStupidWhenDeletingFromEmptyQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldNotDoAnythingStupidWhenDeletingFromEmptyQueue]' passed (0.014 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldNotFetchAnyElementNotExisting]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldNotFetchAnyElementNotExisting]' passed (0.022 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldNotReadMessageIndexUnknownQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldNotReadMessageIndexUnknownQueue]' passed (0.018 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldOnlyRetrieveExistingElementsEventIfMaxAsksForMore]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldOnlyRetrieveExistingElementsEventIfMaxAsksForMore]' passed (0.021 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldPersistAndRetrieveBucketOfOnlyOneElement]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldPersistAndRetrieveBucketOfOnlyOneElement]' passed (0.020 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldReadPersistedMessageIndex]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldReadPersistedMessageIndex]' passed (0.019 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldReturnCountOfMessages]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaPersistentQueueTests testShouldReturnCountOfMessages]' passed (0.020 seconds). Test Suite 'OMSKafkaPersistentQueueTests' passed at 2015-01-05 18:41:50 +0000. Executed 24 tests, with 0 failures (0 unexpected) in 0.505 (0.515) seconds Test Suite 'OMSKafkaRACClientTests' started at 2015-01-05 18:41:50 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaRACClientTests testPeekOutOfOrder]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACClientTests testPeekOutOfOrder]' passed (0.035 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACClientTests testShouldPeekSpecificRange]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACClientTests testShouldPeekSpecificRange]' passed (0.028 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACClientTests testStreamsPacketsUntilTheEnd]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACClientTests testStreamsPacketsUntilTheEnd]' passed (6.405 seconds). Test Suite 'OMSKafkaRACClientTests' passed at 2015-01-05 18:41:57 +0000. Executed 3 tests, with 0 failures (0 unexpected) in 6.467 (6.469) seconds Test Suite 'OMSKafkaRACConsumerTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testPeekedElementsThatAreNotAcknowledgedShouldCountAsRemaining]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testPeekedElementsThatAreNotAcknowledgedShouldCountAsRemaining]' passed (0.034 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldBeBehind]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldBeBehind]' passed (0.029 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldConsumeOnlyElementOfQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldConsumeOnlyElementOfQueue]' passed (0.031 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldConsumeOnlyTwoElementsOutOfThree]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldConsumeOnlyTwoElementsOutOfThree]' passed (0.027 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldFetchFromPreviousAcknowledgement]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldFetchFromPreviousAcknowledgement]' passed (0.027 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldGetRemainingCountWhenNothingHasBeenAcknowledged]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldGetRemainingCountWhenNothingHasBeenAcknowledged]' passed (0.028 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldGetRemainingCountWhenSomeElementsHaveBeenAcknowledged]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldGetRemainingCountWhenSomeElementsHaveBeenAcknowledged]' passed (0.029 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldNotFetchAnyDataFromEmptyQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldNotFetchAnyDataFromEmptyQueue]' passed (0.028 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldPersistOffset]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldPersistOffset]' passed (0.029 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldSignalWhenQueueSizeIncreases]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testShouldSignalWhenQueueSizeIncreases]' passed (0.029 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testSignalsWhenMessagesAreConsumed]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testSignalsWhenMessagesAreConsumed]' passed (0.030 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testUpdatesZookeeper]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaRACConsumerTests testUpdatesZookeeper]' passed (0.027 seconds). Test Suite 'OMSKafkaRACConsumerTests' passed at 2015-01-05 18:41:57 +0000. Executed 12 tests, with 0 failures (0 unexpected) in 0.348 (0.353) seconds Test Suite 'OMSKafkaSynchronousConsumerTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaSynchronousConsumerTests test]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaSynchronousConsumerTests test]' passed (0.030 seconds). Test Suite 'OMSKafkaSynchronousConsumerTests' passed at 2015-01-05 18:41:57 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.030 (0.030) seconds Test Suite 'OMSKafkaTopicTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testEmptyQueueShouldNotReturnAnyNewestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testEmptyQueueShouldNotReturnAnyNewestMessage]' passed (0.029 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testEmptyQueueShouldNotReturnAnyOldestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testEmptyQueueShouldNotReturnAnyOldestMessage]' passed (0.030 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueuesShouldNotMixUp]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueuesShouldNotMixUp]' passed (0.031 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueueWithOneElementShouldReturnItAsNewestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueueWithOneElementShouldReturnItAsNewestMessage]' passed (0.027 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueueWithOneElementShouldReturnItAsOldestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueueWithOneElementShouldReturnItAsOldestMessage]' passed (0.028 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueueWithTwoElementsShouldReturnNewestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueueWithTwoElementsShouldReturnNewestMessage]' passed (0.031 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueueWithTwoMessagesShouldReturnOldestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testQueueWithTwoMessagesShouldReturnOldestMessage]' passed (0.033 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldFetchFromGivenOffset]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldFetchFromGivenOffset]' passed (0.026 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldIncrementsOffsets]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldIncrementsOffsets]' passed (0.029 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldNotFetchAnyDataFromEmptyQueue]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldNotFetchAnyDataFromEmptyQueue]' passed (0.030 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldNotFetchAnyDataWhenMaxResultsIsZero]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldNotFetchAnyDataWhenMaxResultsIsZero]' passed (0.028 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldNotFetchDeletedOffsets]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldNotFetchDeletedOffsets]' passed (0.028 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldUpdateZookeeper]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTopicTests testShouldUpdateZookeeper]' passed (0.025 seconds). Test Suite 'OMSKafkaTopicTests' passed at 2015-01-05 18:41:57 +0000. Executed 13 tests, with 0 failures (0 unexpected) in 0.375 (0.380) seconds Test Suite 'OMSKafkaTransientQueueTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testDeletingFromEmptyQueueShouldNotDoAnything]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testDeletingFromEmptyQueueShouldNotDoAnything]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testFilteringEmptyBufferShouldReturnEmptyArray]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testFilteringEmptyBufferShouldReturnEmptyArray]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldBeOverCapacity]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldBeOverCapacity]' passed (0.032 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldCountFiveMessages]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldCountFiveMessages]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldCountZeroMessages]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldCountZeroMessages]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldDeleteAllElements]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldDeleteAllElements]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldFetchAllMessages]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldFetchAllMessages]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldFetchSomeMessagesFromOffset0]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldFetchSomeMessagesFromOffset0]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldFetchSomeMessagesFromOffset2]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldFetchSomeMessagesFromOffset2]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldFilterBufferShouldOnlyKeepRequestedElements]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldFilterBufferShouldOnlyKeepRequestedElements]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldHaveMessagesBeforeOrEqual4]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldHaveMessagesBeforeOrEqual4]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldHaveMessagesBeforeOrEqual5]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldHaveMessagesBeforeOrEqual5]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldHaveMessagesBeforeOrEqual7]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldHaveMessagesBeforeOrEqual7]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldHaveMessagesBeforeOrEqual9]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldHaveMessagesBeforeOrEqual9]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldKeepLastElement]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldKeepLastElement]' passed (0.033 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldNotBeOverCapacity]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldNotBeOverCapacity]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldNotFetchAnyMessageFromEmptyStore]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldNotFetchAnyMessageFromEmptyStore]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldNotReturnNeestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldNotReturnNeestMessage]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldNotReturnOldestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldNotReturnOldestMessage]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldReturnNewestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldReturnNewestMessage]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldReturnOldestMessage]' started. Test Case '-[OMPlus_DemoTests.OMSKafkaTransientQueueTests testShouldReturnOldestMessage]' passed (0.000 seconds). Test Suite 'OMSKafkaTransientQueueTests' passed at 2015-01-05 18:41:57 +0000. Executed 21 tests, with 0 failures (0 unexpected) in 0.074 (0.099) seconds Test Suite 'OMSNSUUIDTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSNSUUIDTests testEquality]' started. Test Case '-[OMPlus_DemoTests.OMSNSUUIDTests testEquality]' passed (0.000 seconds). Test Suite 'OMSNSUUIDTests' passed at 2015-01-05 18:41:57 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.000 (0.001) seconds Test Suite 'OMSSpecificationIssueStoreTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSSpecificationIssueStoreTests testShouldCreateIssue]' started. Test Case '-[OMPlus_DemoTests.OMSSpecificationIssueStoreTests testShouldCreateIssue]' passed (0.020 seconds). Test Suite 'OMSSpecificationIssueStoreTests' passed at 2015-01-05 18:41:57 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.020 (0.021) seconds Test Suite 'OMSTimeInHrZoneGoalAlerterTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSTimeInHrZoneGoalAlerterTests testAnotherZoneAchieved]' started. Test Case '-[OMPlus_DemoTests.OMSTimeInHrZoneGoalAlerterTests testAnotherZoneAchieved]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSTimeInHrZoneGoalAlerterTests testZoneAchieved]' started. Test Case '-[OMPlus_DemoTests.OMSTimeInHrZoneGoalAlerterTests testZoneAchieved]' passed (0.001 seconds). Test Case '-[OMPlus_DemoTests.OMSTimeInHrZoneGoalAlerterTests testZoneEntered]' started. Test Case '-[OMPlus_DemoTests.OMSTimeInHrZoneGoalAlerterTests testZoneEntered]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSTimeInHrZoneGoalAlerterTests testZoneLeft]' started. Test Case '-[OMPlus_DemoTests.OMSTimeInHrZoneGoalAlerterTests testZoneLeft]' passed (0.001 seconds). Test Suite 'OMSTimeInHrZoneGoalAlerterTests' passed at 2015-01-05 18:41:57 +0000. Executed 4 tests, with 0 failures (0 unexpected) in 0.002 (0.040) seconds Test Suite 'OMSURIParserTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSURIParserTests testShouldParseNoParameter]' started. Test Case '-[OMPlus_DemoTests.OMSURIParserTests testShouldParseNoParameter]' passed (0.000 seconds). Test Case '-[OMPlus_DemoTests.OMSURIParserTests testShouldParseOneParameter]' started. Test Case '-[OMPlus_DemoTests.OMSURIParserTests testShouldParseOneParameter]' passed (0.007 seconds). Test Case '-[OMPlus_DemoTests.OMSURIParserTests testShouldParseTwoParameters]' started. Test Case '-[OMPlus_DemoTests.OMSURIParserTests testShouldParseTwoParameters]' passed (0.039 seconds). Test Suite 'OMSURIParserTests' passed at 2015-01-05 18:41:57 +0000. Executed 3 tests, with 0 failures (0 unexpected) in 0.046 (0.048) seconds Test Suite 'OMSUserTraitsRegistrationTests' started at 2015-01-05 18:41:57 +0000 Test Case '-[OMPlus_DemoTests.OMSUserTraitsRegistrationTests testShouldChangedUserTraitsHeight]' started. Test Case '-[OMPlus_DemoTests.OMSUserTraitsRegistrationTests testShouldChangedUserTraitsHeight]' passed (0.016 seconds). Test Case '-[OMPlus_DemoTests.OMSUserTraitsRegistrationTests testShouldCorrectUserTraitsHeight]' started. Test Case '-[OMPlus_DemoTests.OMSUserTraitsRegistrationTests testShouldCorrectUserTraitsHeight]' passed (0.015 seconds). Test Case '-[OMPlus_DemoTests.OMSUserTraitsRegistrationTests testShouldRegisterUserTraits]' started. Test Case '-[OMPlus_DemoTests.OMSUserTraitsRegistrationTests testShouldRegisterUserTraits]' passed (0.016 seconds). Test Suite 'OMSUserTraitsRegistrationTests' passed at 2015-01-05 18:41:58 +0000. Executed 3 tests, with 0 failures (0 unexpected) in 0.048 (0.049) seconds Test Suite 'OMSWeightUnitsConverterTests' started at 2015-01-05 18:41:58 +0000 Test Case '-[OMPlus_DemoTests.OMSWeightUnitsConverterTests testShouldMapToInternationalMetric]' started. Test Case '-[OMPlus_DemoTests.OMSWeightUnitsConverterTests testShouldMapToInternationalMetric]' passed (0.000 seconds). Test Suite 'OMSWeightUnitsConverterTests' passed at 2015-01-05 18:41:58 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.000 (0.001) seconds Test Suite 'OMSWorkoutGeneratorTests' started at 2015-01-05 18:41:58 +0000 Test Case '-[OMPlus_DemoTests.OMSWorkoutGeneratorTests testPacketsGoingBackInTime]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutGeneratorTests testPacketsGoingBackInTime]' passed (0.017 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutGeneratorTests testWorkoutWithoutPackets]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutGeneratorTests testWorkoutWithoutPackets]' passed (0.001 seconds). Test Suite 'OMSWorkoutGeneratorTests' passed at 2015-01-05 18:41:58 +0000. Executed 2 tests, with 0 failures (0 unexpected) in 0.018 (0.019) seconds Test Suite 'OMSWorkoutReportProjectorTests' started at 2015-01-05 18:41:58 +0000 Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testGeneratesLiveReport]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testGeneratesLiveReport]' passed (0.102 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testMarksForGCWhenIdle]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testMarksForGCWhenIdle]' passed (0.041 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testPastReportsAreGenerated]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testPastReportsAreGenerated]' passed (0.532 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testTwoLiveReportsGenerated]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testTwoLiveReportsGenerated]' passed (0.038 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testUpdatesAggregateWorkoutStats]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testUpdatesAggregateWorkoutStats]' passed (0.143 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testZeroesDontContributeToAggregates]' started. /Users/clement/Desktop/Repos/omplus-sdk/OMPlus-SDK/OMPlus-Demo-Tests/OMSWorkoutReportProjectorTests.swift:256: error: -[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testZeroesDontContributeToAggregates] : XCTAssertEqual failed: ("18") is not equal to ("15") - peak HR from second workout Test Case '-[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testZeroesDontContributeToAggregates]' failed (0.098 seconds). Test Suite 'OMSWorkoutReportProjectorTests' failed at 2015-01-05 18:41:59 +0000. Executed 6 tests, with 1 failure (0 unexpected) in 0.954 (0.956) seconds Test Suite 'OMSWorkoutStoreTests' started at 2015-01-05 18:41:59 +0000 Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testRetrieveWorkoutReportViewModelWithBestScore]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testRetrieveWorkoutReportViewModelWithBestScore]' passed (0.018 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testSavesAggregateWorkoutStats]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testSavesAggregateWorkoutStats]' passed (0.024 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldAssignReportToWorkout]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldAssignReportToWorkout]' passed (0.021 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldBeIdempotentWhenAssigningReportToWorkout]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldBeIdempotentWhenAssigningReportToWorkout]' passed (0.014 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldBeIdempotentWhenProcessingWorkoutEndTaggedEvent]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldBeIdempotentWhenProcessingWorkoutEndTaggedEvent]' passed (0.011 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldBeIdempotentWhenProcessingWorkoutStartTaggedEvent]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldBeIdempotentWhenProcessingWorkoutStartTaggedEvent]' passed (0.019 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldCreateWorkout]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldCreateWorkout]' passed (0.011 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetAllWorkouts]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetAllWorkouts]' passed (0.012 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetCompletedWorkouts]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetCompletedWorkouts]' passed (0.014 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetCompletedWorkoutsWithoutReports]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetCompletedWorkoutsWithoutReports]' passed (0.017 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetCurrentWorkout]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetCurrentWorkout]' passed (0.014 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetIncompleteWorkouts]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldGetIncompleteWorkouts]' passed (0.014 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldNotGetCurrentWorkout]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldNotGetCurrentWorkout]' passed (0.013 seconds). Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldRetrieveWorkoutsWithinTimeRange]' started. Test Case '-[OMPlus_DemoTests.OMSWorkoutStoreTests testShouldRetrieveWorkoutsWithinTimeRange]' passed (0.017 seconds). Test Suite 'OMSWorkoutStoreTests' passed at 2015-01-05 18:41:59 +0000. Executed 14 tests, with 0 failures (0 unexpected) in 0.218 (0.224) seconds Test Suite 'OMSZookeeperTests' started at 2015-01-05 18:41:59 +0000 Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testFlushesToDisk]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testFlushesToDisk]' passed (0.007 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testInitialOffsetConsumedShouldBeNil]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testInitialOffsetConsumedShouldBeNil]' passed (0.003 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testInitialPersistentOffsetShouldBeNil]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testInitialPersistentOffsetShouldBeNil]' passed (0.004 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testInitialTransientOffsetShouldBeNil]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testInitialTransientOffsetShouldBeNil]' passed (0.004 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldNotifyOfLastOffsetConsumedUpdate]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldNotifyOfLastOffsetConsumedUpdate]' passed (0.005 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldNotifyOfLastPersistentOffsetUpdate]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldNotifyOfLastPersistentOffsetUpdate]' passed (0.005 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldNotifyOfLastTransientOffsetUpdate]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldNotifyOfLastTransientOffsetUpdate]' passed (0.004 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldUpdateLastConsumerOffset]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldUpdateLastConsumerOffset]' passed (0.004 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldUpdateLastPersistentOffset]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldUpdateLastPersistentOffset]' passed (0.003 seconds). Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldUpdateLastTransientOffset]' started. Test Case '-[OMPlus_DemoTests.OMSZookeeperTests testShouldUpdateLastTransientOffset]' passed (0.003 seconds). Test Suite 'OMSZookeeperTests' passed at 2015-01-05 18:41:59 +0000. Executed 10 tests, with 0 failures (0 unexpected) in 0.042 (0.093) seconds Test Suite 'OMPlus-DemoTests.xctest' failed at 2015-01-05 18:41:59 +0000. Executed 205 tests, with 1 failure (0 unexpected) in 19.611 (19.948) seconds Test Suite 'All tests' failed at 2015-01-05 18:41:59 +0000. Executed 205 tests, with 1 failure (0 unexpected) in 19.611 (19.949) seconds Failing tests: -[OMPlus_DemoTests.OMSWorkoutReportProjectorTests testZeroesDontContributeToAggregates] ** TEST FAILED ** ================================================ FILE: src/test/resources/XCTest_output_passing_1.txt ================================================ Test Suite 'All tests' started at 2014-12-12 04:48:53 +0000 Test Suite 'UnitTestsCardExampleTests.xctest' started at 2014-12-12 04:48:53 +0000 Test Suite 'CardTestCase' started at 2014-12-12 04:48:53 +0000 Test Case '-[CardTestCase testDoesNotMatchDifferentCard]' started. Test Case '-[CardTestCase testDoesNotMatchDifferentCard]' passed (0.000 seconds). Test Case '-[CardTestCase testMatchesDifferentCardWithSameContents]' started. Test Case '-[CardTestCase testMatchesDifferentCardWithSameContents]' passed (0.000 seconds). Test Case '-[CardTestCase testMatchesForAtLeastOneCard]' started. Test Case '-[CardTestCase testMatchesForAtLeastOneCard]' passed (0.000 seconds). Test Suite 'CardTestCase' passed at 2014-12-12 04:48:53 +0000. Executed 3 tests, with 0 failures (0 unexpected) in 0.001 (0.002) seconds Test Suite 'DeckTestCase' started at 2014-12-12 04:48:53 +0000 Test Case '-[DeckTestCase testDeckWithMultipleCardsWillRandomlyDrawThemAll]' started. Test Case '-[DeckTestCase testDeckWithMultipleCardsWillRandomlyDrawThemAll]' passed (0.001 seconds). Test Case '-[DeckTestCase testDrawCardFromEmptyDeckAnswersNoCard]' started. Test Case '-[DeckTestCase testDrawCardFromEmptyDeckAnswersNoCard]' passed (0.000 seconds). Test Case '-[DeckTestCase testDrawnRandomCardsAreDifferent]' started. Test Case '-[DeckTestCase testDrawnRandomCardsAreDifferent]' passed (0.000 seconds). Test Case '-[DeckTestCase testOneCardDeckShouldAnswerThatCard]' started. Test Case '-[DeckTestCase testOneCardDeckShouldAnswerThatCard]' passed (0.000 seconds). Test Suite 'DeckTestCase' passed at 2014-12-12 04:48:53 +0000. Executed 4 tests, with 0 failures (0 unexpected) in 0.001 (0.003) seconds Test Suite 'PlayingCardDeckTestCase' started at 2014-12-12 04:48:53 +0000 Test Case '-[PlayingCardDeckTestCase testPlayingCardDeckAnswersPlayingCards]' started. Test Case '-[PlayingCardDeckTestCase testPlayingCardDeckAnswersPlayingCards]' passed (0.001 seconds). Test Case '-[PlayingCardDeckTestCase testPlayingCardDeckHasTheCorrectInitialCards]' started. Test Case '-[PlayingCardDeckTestCase testPlayingCardDeckHasTheCorrectInitialCards]' passed (0.001 seconds). Test Suite 'PlayingCardDeckTestCase' passed at 2014-12-12 04:48:53 +0000. Executed 2 tests, with 0 failures (0 unexpected) in 0.001 (0.002) seconds Test Suite 'PlayingCardTestCase' started at 2014-12-12 04:48:53 +0000 Test Case '-[PlayingCardTestCase testSetSuitAnyValidAccepted]' started. Test Case '-[PlayingCardTestCase testSetSuitAnyValidAccepted]' passed (0.000 seconds). Test Case '-[PlayingCardTestCase testSetSuitInvalidRejected]' started. Test Case '-[PlayingCardTestCase testSetSuitInvalidRejected]' passed (0.000 seconds). Test Case '-[PlayingCardTestCase testTheValidSuits]' started. Test Case '-[PlayingCardTestCase testTheValidSuits]' passed (0.000 seconds). Test Suite 'PlayingCardTestCase' passed at 2014-12-12 04:48:53 +0000. Executed 3 tests, with 0 failures (0 unexpected) in 0.001 (0.002) seconds Test Suite 'UnitTestsCardExampleTests.xctest' passed at 2014-12-12 04:48:53 +0000. Executed 12 tests, with 0 failures (0 unexpected) in 0.004 (0.015) seconds Test Suite 'All tests' passed at 2014-12-12 04:48:53 +0000. Executed 12 tests, with 0 failures (0 unexpected) in 0.004 (0.017) seconds ** TEST SUCCEEDED ** ================================================ FILE: src/test/resources/xcodebuildhelp-invalid.txt ================================================ xcodebuild -help output SampleTarget1 Extra text here. TestSampleTarget1 Extra text here. Extra text here. ================================================ FILE: src/test/resources/xcodebuildhelp-valid.txt ================================================ xcodebuild -help output -SampleTarget1 Extra text here. -TestSampleTarget1 Extra text here. Extra text here. ================================================ FILE: src/test/resources/xcodebuildlist-invalid1.txt ================================================ Information about project "SampleXcodeProject": Targets: SampleTarget1 SampleTarget2 TestSampleTarget1 TestSampleTarget2 Build Configurations: BuildConfiguration1 BuildConfiguration2 If no build configuration is specified and -scheme is not passed then "Release" is used. Schemes: SampleScheme1 SampleScheme2 ================================================ FILE: src/test/resources/xcodebuildlist-invalid2.txt ================================================ Information about project "SampleXcodeProject": Targets SampleTarget1 SampleTarget2 TestSampleTarget1 TestSampleTarget2 Build Configurations BuildConfiguration1 BuildConfiguration2 If no build configuration is specified and -scheme is not passed then "Release" is used. Schemes SampleScheme1 SampleScheme2 ================================================ FILE: src/test/resources/xcodebuildlist-valid.txt ================================================ Information about project "SampleXcodeProject": Targets: SampleTarget1 SampleTarget2 TestSampleTarget1 TestSampleTarget2 Build Configurations: BuildConfiguration1 BuildConfiguration2 If no build configuration is specified and -scheme is not passed then "Release" is used. Schemes: SampleScheme1 SampleScheme2