diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml new file mode 100644 index 00000000..9f6867db --- /dev/null +++ b/.github/workflows/testflight.yml @@ -0,0 +1,70 @@ +name: "TestFlight ⚙️" + +on: + repository_dispatch: + types: [testflight] + +jobs: + test_build: + runs-on: macos-14 + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: git Checkout + if: ${{ github.event.client_payload.hasCheckoutCommit }} + run: | + git checkout ${{ github.event.client_payload.commitSHA }} + + - run: 'echo "$SSH_KEY" > key' + shell: bash + env: + SSH_KEY: ${{secrets.P12_PASSWORD}} + + - name: Install the Apple certificate and provisioning profile + env: + BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} + BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }} + KEYCHAIN_PASSWORD: "CI_PASSWORD" + P12_PASSWORD: ${{ secrets.P12_PASSWORD }} + run: | + # create variables + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 + PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + + # import certificate and provisioning profile from secrets + echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH + echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH + + # create temporary keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + + # import certificate to keychain + security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH + + # apply provisioning profile + mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles + sudo mkdir -p /Library/MobileDevice/Provisioning\ Profiles + cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles + sudo cp $PP_PATH /Library/MobileDevice/Provisioning\ Profiles + + - name: Build and Upload to TestFlight + run: sudo fastlane testFlightLane \ + keyID:${{ secrets.APP_STORE_KEY_ID }} \ + issuerID:${{ secrets.APP_STORE_ISSUER_ID }} \ + keyContents:${{ secrets.APP_STORE_KEY_CONTENTS }} \ + scheme:${{ github.event.client_payload.scheme }} \ + codeSign64:${{ secrets.CODE_SIGN_64 }} \ + profileName64:${{ secrets.PROFILE_NAME_64 }} \ + xcodeVersion:${{ github.event.client_payload.xcodeVersion }} \ + build:${{ github.event.client_payload.build }} \ + version:${{ github.event.client_payload.version }} \ No newline at end of file diff --git a/fastlane/Fastfile.swift b/fastlane/Fastfile.swift index 8f43a1cc..5ad36cba 100644 --- a/fastlane/Fastfile.swift +++ b/fastlane/Fastfile.swift @@ -63,6 +63,82 @@ class Fastfile: LaneFile { ) } + // MARK: TestFlight + + // TODO: verify tvOS + func testFlightLane(withOptions options: [String: String]?) { + + guard let options, + let keyID = options["keyID"], + let issuerID = options["issuerID"], + let keyContents = options["keyContents"], + let scheme = options["scheme"], + let codeSign64 = options["codeSign64"], + let profileName64 = options["profileName64"] + else { + puts(message: "ERROR: missing or incorrect options") + exit(1) + } + + guard let decodedCodeSignIdentity = decodeBase64(encoded: codeSign64) else { + puts(message: "ERROR: code sign identity not valid base 64") + exit(1) + } + + guard let profileName = decodeBase64(encoded: profileName64) else { + puts(message: "ERROR: profile name not valid base 64") + exit(1) + } + + if let xcodeVersion = options["xcodeVersion"] { + xcodes(version: xcodeVersion) + } + + appStoreConnectApiKey( + keyId: keyID, + issuerId: .userDefined(issuerID), + keyContent: .userDefined(keyContents), + isKeyContentBase64: true, + duration: 1200, + inHouse: false + ) + + updateCodeSigningSettings( + path: "Swiftfin.xcodeproj", + useAutomaticSigning: false, + codeSignIdentity: .userDefined(decodedCodeSignIdentity), + profileName: .userDefined(profileName) + ) + + if let version = options["version"] { + incrementVersionNumber( + versionNumber: .userDefined(version), + xcodeproj: "Swiftfin.xcodeproj" + ) + } + + if let build = options["build"] { + incrementBuildNumber( + buildNumber: .userDefined(build), + xcodeproj: "Swiftfin.xcodeproj" + ) + } else { + incrementBuildNumber( + xcodeproj: "Swiftfin.xcodeproj" + ) + } + + buildApp( + scheme: .userDefined(scheme), + skipArchive: .userDefined(false), + skipProfileDetection: false + ) + + uploadToTestflight( + ipa: "Swiftfin.ipa" + ) + } + // MARK: Utilities private func decodeBase64(encoded: String) -> String? { diff --git a/fastlane/swift/DeliverfileProtocol.swift b/fastlane/swift/DeliverfileProtocol.swift index f0e215cc..6ffc44eb 100644 --- a/fastlane/swift/DeliverfileProtocol.swift +++ b/fastlane/swift/DeliverfileProtocol.swift @@ -95,7 +95,7 @@ public protocol DeliverfileProtocol: AnyObject { /// Path to the app rating's config var appRatingConfigPath: String? { get } - /// Extra information for the submission (e.g. compliance specifications, IDFA settings) + /// Extra information for the submission (e.g. compliance specifications) var submissionInformation: [String: Any]? { get } /// The ID of your App Store Connect team if you're in multiple teams @@ -272,4 +272,4 @@ public extension DeliverfileProtocol { // Please don't remove the lines below // They are used to detect outdated files -// FastlaneRunnerAPIVersion [0.9.124] +// FastlaneRunnerAPIVersion [0.9.127] diff --git a/fastlane/swift/Fastlane.swift b/fastlane/swift/Fastlane.swift index 3c6375c7..cb306439 100644 --- a/fastlane/swift/Fastlane.swift +++ b/fastlane/swift/Fastlane.swift @@ -190,7 +190,7 @@ public func appStoreBuildNumber(apiKeyPath: OptionalConfigValue = .fast - parameters: - keyId: The key ID - - issuerId: The issuer ID + - issuerId: The issuer ID. It can be nil if the key is individual API key - keyFilepath: The path to the key p8 file - keyContent: The content of the key p8 file - isKeyContentBase64: Whether :key_content is Base64 encoded or not @@ -201,7 +201,7 @@ public func appStoreBuildNumber(apiKeyPath: OptionalConfigValue = .fast Load the App Store Connect API token to use in other fastlane tools and actions */ public func appStoreConnectApiKey(keyId: String, - issuerId: String, + issuerId: OptionalConfigValue = .fastlaneDefault(nil), keyFilepath: OptionalConfigValue = .fastlaneDefault(nil), keyContent: OptionalConfigValue = .fastlaneDefault(nil), isKeyContentBase64: OptionalConfigValue = .fastlaneDefault(false), @@ -210,7 +210,7 @@ public func appStoreConnectApiKey(keyId: String, setSpaceshipToken: OptionalConfigValue = .fastlaneDefault(true)) { let keyIdArg = RubyCommand.Argument(name: "key_id", value: keyId, type: nil) - let issuerIdArg = RubyCommand.Argument(name: "issuer_id", value: issuerId, type: nil) + let issuerIdArg = issuerId.asRubyArgument(name: "issuer_id", type: nil) let keyFilepathArg = keyFilepath.asRubyArgument(name: "key_filepath", type: nil) let keyContentArg = keyContent.asRubyArgument(name: "key_content", type: nil) let isKeyContentBase64Arg = isKeyContentBase64.asRubyArgument(name: "is_key_content_base64", type: nil) @@ -674,7 +674,7 @@ public func appledoc(input: [String], - resetRatings: Reset the summary rating when you release a new version of the application - priceTier: The price tier of this application - appRatingConfigPath: Path to the app rating's config - - submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings) + - submissionInformation: Extra information for the submission (e.g. compliance specifications) - teamId: The ID of your App Store Connect team if you're in multiple teams - teamName: The name of your App Store Connect team if you're in multiple teams - devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID! @@ -3714,7 +3714,7 @@ public func deleteKeychain(name: OptionalConfigValue = .fastlaneDefault - resetRatings: Reset the summary rating when you release a new version of the application - priceTier: The price tier of this application - appRatingConfigPath: Path to the app rating's config - - submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings) + - submissionInformation: Extra information for the submission (e.g. compliance specifications) - teamId: The ID of your App Store Connect team if you're in multiple teams - teamName: The name of your App Store Connect team if you're in multiple teams - devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID! @@ -4096,7 +4096,7 @@ public func downloadAppPrivacyDetailsFromAppStore(username: String, - appIdentifier: The bundle identifier of your app - teamId: The ID of your App Store Connect team if you're in multiple teams - teamName: The name of your App Store Connect team if you're in multiple teams - - platform: The app platform for dSYMs you wish to download (ios, appletvos) + - platform: The app platform for dSYMs you wish to download (ios, xros, appletvos) - version: The app version for dSYMs you wish to download, pass in 'latest' to download only the latest build's dSYMs or 'live' to download only the live version dSYMs - buildNumber: The app build_number for dSYMs you wish to download - minVersion: The minimum app version for dSYMs you wish to download @@ -9707,7 +9707,7 @@ public func setBuildNumberRepository(useHgRevisionNumber: OptionalConfigValue = .fastlaneDefault(nil - xcprettyOutput: Specifies the output type for xcpretty. eg. 'test', or 'simple' - xcprettyArgs: Pass in xcpretty additional command line arguments (e.g. '--test --no-color' or '--tap --no-utf'), requires xcpretty_output to be specified also - verbose: Increase verbosity of informational output + - veryVerbose: Increase verbosity to include debug output - simulator: Specifies the simulator to pass for Swift Compiler (one of: iphonesimulator, macosx) - simulatorArch: Specifies the architecture of the simulator to pass for Swift Compiler (one of: x86_64, arm64). Requires the simulator option to be specified also, otherwise, it's ignored */ @@ -10953,6 +10954,7 @@ public func spm(command: String = "build", xcprettyOutput: OptionalConfigValue = .fastlaneDefault(nil), xcprettyArgs: OptionalConfigValue = .fastlaneDefault(nil), verbose: OptionalConfigValue = .fastlaneDefault(false), + veryVerbose: OptionalConfigValue = .fastlaneDefault(false), simulator: OptionalConfigValue = .fastlaneDefault(nil), simulatorArch: String = "arm64") { @@ -10968,6 +10970,7 @@ public func spm(command: String = "build", let xcprettyOutputArg = xcprettyOutput.asRubyArgument(name: "xcpretty_output", type: nil) let xcprettyArgsArg = xcprettyArgs.asRubyArgument(name: "xcpretty_args", type: nil) let verboseArg = verbose.asRubyArgument(name: "verbose", type: nil) + let veryVerboseArg = veryVerbose.asRubyArgument(name: "very_verbose", type: nil) let simulatorArg = simulator.asRubyArgument(name: "simulator", type: nil) let simulatorArchArg = RubyCommand.Argument(name: "simulator_arch", value: simulatorArch, type: nil) let array: [RubyCommand.Argument?] = [commandArg, @@ -10982,6 +10985,7 @@ public func spm(command: String = "build", xcprettyOutputArg, xcprettyArgsArg, verboseArg, + veryVerboseArg, simulatorArg, simulatorArchArg] let args: [RubyCommand.Argument] = array @@ -12536,7 +12540,7 @@ public func uploadSymbolsToSentry(apiHost: String = "https://app.getsentry.com/a - resetRatings: Reset the summary rating when you release a new version of the application - priceTier: The price tier of this application - appRatingConfigPath: Path to the app rating's config - - submissionInformation: Extra information for the submission (e.g. compliance specifications, IDFA settings) + - submissionInformation: Extra information for the submission (e.g. compliance specifications) - teamId: The ID of your App Store Connect team if you're in multiple teams - teamName: The name of your App Store Connect team if you're in multiple teams - devPortalTeamId: The short ID of your Developer Portal team, if you're in multiple teams. Different from your iTC team ID! @@ -13594,7 +13598,7 @@ public func xcov(workspace: OptionalConfigValue = .fastlaneDefault(nil) coverallsServiceJobId: OptionalConfigValue = .fastlaneDefault(nil), coverallsRepoToken: OptionalConfigValue = .fastlaneDefault(nil), xcconfig: OptionalConfigValue = .fastlaneDefault(nil), - ideFoundationPath: String = "/Applications/Xcode-15.3.0.app/Contents/Developer/../Frameworks/IDEFoundation.framework/Versions/A/IDEFoundation", + ideFoundationPath: String = "/Applications/Xcode_15.4.app/Contents/Developer/../Frameworks/IDEFoundation.framework/Versions/A/IDEFoundation", legacySupport: OptionalConfigValue = .fastlaneDefault(false)) { let workspaceArg = workspace.asRubyArgument(name: "workspace", type: nil) @@ -13797,4 +13801,4 @@ public let snapshotfile: Snapshotfile = .init() // Please don't remove the lines below // They are used to detect outdated files -// FastlaneRunnerAPIVersion [0.9.177] +// FastlaneRunnerAPIVersion [0.9.180] diff --git a/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj b/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj index 6d3f071e..48ebd670 100644 --- a/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +++ b/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj @@ -404,6 +404,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "-"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 4.0; @@ -416,6 +417,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "-"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.12; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 4.0; }; diff --git a/fastlane/swift/GymfileProtocol.swift b/fastlane/swift/GymfileProtocol.swift index 6d0594f0..00750295 100644 --- a/fastlane/swift/GymfileProtocol.swift +++ b/fastlane/swift/GymfileProtocol.swift @@ -208,4 +208,4 @@ public extension GymfileProtocol { // Please don't remove the lines below // They are used to detect outdated files -// FastlaneRunnerAPIVersion [0.9.127] +// FastlaneRunnerAPIVersion [0.9.130] diff --git a/fastlane/swift/MatchfileProtocol.swift b/fastlane/swift/MatchfileProtocol.swift index 90d1e241..bee8d3af 100644 --- a/fastlane/swift/MatchfileProtocol.swift +++ b/fastlane/swift/MatchfileProtocol.swift @@ -228,4 +228,4 @@ public extension MatchfileProtocol { // Please don't remove the lines below // They are used to detect outdated files -// FastlaneRunnerAPIVersion [0.9.121] +// FastlaneRunnerAPIVersion [0.9.124] diff --git a/fastlane/swift/PrecheckfileProtocol.swift b/fastlane/swift/PrecheckfileProtocol.swift index c5fd86d7..8355fe48 100644 --- a/fastlane/swift/PrecheckfileProtocol.swift +++ b/fastlane/swift/PrecheckfileProtocol.swift @@ -52,4 +52,4 @@ public extension PrecheckfileProtocol { // Please don't remove the lines below // They are used to detect outdated files -// FastlaneRunnerAPIVersion [0.9.120] +// FastlaneRunnerAPIVersion [0.9.123] diff --git a/fastlane/swift/ScanfileProtocol.swift b/fastlane/swift/ScanfileProtocol.swift index a4410da9..6885c88d 100644 --- a/fastlane/swift/ScanfileProtocol.swift +++ b/fastlane/swift/ScanfileProtocol.swift @@ -320,4 +320,4 @@ public extension ScanfileProtocol { // Please don't remove the lines below // They are used to detect outdated files -// FastlaneRunnerAPIVersion [0.9.132] +// FastlaneRunnerAPIVersion [0.9.135] diff --git a/fastlane/swift/ScreengrabfileProtocol.swift b/fastlane/swift/ScreengrabfileProtocol.swift index 5a39df67..17fe31dd 100644 --- a/fastlane/swift/ScreengrabfileProtocol.swift +++ b/fastlane/swift/ScreengrabfileProtocol.swift @@ -96,4 +96,4 @@ public extension ScreengrabfileProtocol { // Please don't remove the lines below // They are used to detect outdated files -// FastlaneRunnerAPIVersion [0.9.122] +// FastlaneRunnerAPIVersion [0.9.125] diff --git a/fastlane/swift/SnapshotfileProtocol.swift b/fastlane/swift/SnapshotfileProtocol.swift index 67d20a33..356d00ed 100644 --- a/fastlane/swift/SnapshotfileProtocol.swift +++ b/fastlane/swift/SnapshotfileProtocol.swift @@ -204,4 +204,4 @@ public extension SnapshotfileProtocol { // Please don't remove the lines below // They are used to detect outdated files -// FastlaneRunnerAPIVersion [0.9.116] +// FastlaneRunnerAPIVersion [0.9.119]