diff --git a/.github/project_workflows/add_device_profile.yml b/.github/project_workflows/add_device_profile.yml new file mode 100644 index 00000000..e3bfa5d4 --- /dev/null +++ b/.github/project_workflows/add_device_profile.yml @@ -0,0 +1,58 @@ +name: Test Add device and regenerate profiles with fastlane match + +# SECRETS needed: +### SSH_PRIVATE_KEY for the match Repo +### MATCH_PASSWORD +### APPSTORE_CONNECT_API_KEY +### API_KEY_ID +### ISSUER_ID + +on: + pull_request: + workflow_dispatch: + inputs: + devices: + description: 'JSON of devices. `{"Luka iPhone 6":"1234567890123456789012345678901234567890","Felix iPad Air 2":"abcdefghijklmnopqrstvuwxyzabcdefghijklmn"}`' + required: true + type: string + platform: + description: 'The platform' + required: true + default: 'ios' + type: choice + options: + - ios + - mac + +jobs: + create_files: + name: Create certificates and profiles + runs-on: macOS-latest + steps: + - name: Checkout the repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install SSH key + uses: webfactory/ssh-agent@v0.5.4 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Bundle install + run: bundle install + + - name: Add device and regenerate profiles with match + run: bundle exec fastlane addDevicesGenerateProfiles + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASS }} + DEVICES: ${{ inputs.devices }} + APPSTORE_CONNECT_API_KEY: ${{ secrets.APPSTORE_CONNECT_API_KEY }} + API_KEY_ID: ${{ secrets.API_KEY_ID }} + ISSUER_ID: ${{ secrets.ISSUER_ID }} + PLATFORM: ${{ inputs.platform }} + + - name: Clean up keychain + if: ${{ always() }} + run: bundle exec fastlane remove_keychain + continue-on-error: true diff --git a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift index 972e9250..774b9f09 100644 --- a/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift +++ b/Scripts/Swift/iOSTemplateMaker/Sources/iOSTemplateMaker/SetUpCICDService.swift @@ -7,34 +7,44 @@ struct SetUpCICDService { case github, bitrise, codemagic, later init?(_ name: String) { - switch name.lowercased() { - case "g", "github": - self = .github - case "b", "bitrise": - self = .bitrise - case "c", "codemagic": - self = .codemagic - case "l", "later": - self = .later - default: + let name = name.lowercased() + let mappings: [String: Self] = [ + "g": .github, + "github": .github, + "b": .bitrise, + "bitrise": .bitrise, + "c": .codemagic, + "codemagic": .codemagic, + "l": .later, + "later": .later + ] + + if let matchedCase = mappings[name] { + self = matchedCase + } else { return nil } } } - + enum GithubRunnerType { case macOSLatest, selfHosted, later init?(_ name: String) { - switch name.lowercased() { - case "m", "macOS": - self = .macOSLatest - case "s", "self-hosted": - self = .selfHosted - case "l", "later": - self = .later - default: + let mappings: [String: Self] = [ + "m": .macOSLatest, + "macos": .macOSLatest, + "s": .selfHosted, + "self-hosted": .selfHosted, + "l": .later, + "later": .later + ] + + let name = name.lowercased() + if let matchedCase = mappings[name] { + self = matchedCase + } else { return nil } } @@ -63,10 +73,12 @@ struct SetUpCICDService { fileManager.createDirectory(path: ".github/workflows") switch runnerType { case .macOSLatest: + print("Configured to run on the latest macOS.") fileManager.moveFiles(in: ".github/project_workflows", to: ".github/workflows") fileManager.removeItems(in: ".github/project_workflows") fileManager.removeItems(in: ".github/self_hosted_project_workflows") case .selfHosted: + print("Configured to run on self-hosted.") fileManager.moveFiles(in: ".github/self_hosted_project_workflows", to: ".github/workflows") fileManager.removeItems(in: ".github/project_workflows") fileManager.removeItems(in: ".github/self_hosted_project_workflows") diff --git a/fastlane/Constants/Constant.swift b/fastlane/Constants/Constant.swift index 6c47444c..155852e1 100644 --- a/fastlane/Constants/Constant.swift +++ b/fastlane/Constants/Constant.swift @@ -28,12 +28,20 @@ enum Constant { static let appleProductionTeamId = "<#teamId#>" static let keychainName = "{PROJECT_NAME}_keychain" static let matchURL = "git@github.com:{organization}/{repo}.git" - static let apiKey: [String: Any] = [ - "key_id" : Secret.appStoreKeyIdKey, - "issuer_id": Secret.appStoreIssuerIdKey, - "key": Secret.appstoreConnectAPIKey, - "in_house": false - ] + static let apiKey: [String: Any] = { + var key = Secret.appstoreConnectAPIKey + if let data = Data(base64Encoded: Secret.appstoreConnectAPIKey), + let decodedKey = String(data: data, encoding: .utf8) { + key = decodedKey + } + + return [ + "key_id" : Secret.appStoreKeyIdKey, + "issuer_id": Secret.appStoreIssuerIdKey, + "key": key, + "in_house": false + ] + }() // MARK: - Path diff --git a/fastlane/Constants/Secret.swift b/fastlane/Constants/Secret.swift index 12f37911..6bc1ed25 100644 --- a/fastlane/Constants/Secret.swift +++ b/fastlane/Constants/Secret.swift @@ -18,4 +18,8 @@ enum Secret { static let appStoreIssuerIdKey = EnvironmentParser.string(key: "ISSUER_ID") static let bumpAppStoreBuildNumber = EnvironmentParser.bool(key: "BUMP_APP_STORE_BUILD_NUMBER") + + static let devices = EnvironmentParser.string(key: "DEVICES") + + static let platform = EnvironmentParser.string(key: "PLATFORM") } diff --git a/fastlane/Fastfile.swift b/fastlane/Fastfile.swift index 5052b7ad..d8e1f09d 100644 --- a/fastlane/Fastfile.swift +++ b/fastlane/Fastfile.swift @@ -176,6 +176,24 @@ class Fastfile: LaneFile { Match.syncCodeSigning(type: .adHoc, environment: .staging, isForce: true) } + func addDevicesGenerateProfilesLane() { + desc("Add device and regenerate profiles with match") + + guard let data = Secret.devices.data(using: .utf8), + let devices = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else { + return + } + registerDevices( + devices: .userDefined(devices), + apiKey: .userDefined(Constant.apiKey), + teamId: .userDefined(Constant.appleStagingTeamId), + platform: Secret.platform + ) + + Match.syncCodeSigning(type: .development, environment: .staging, isForce: true) + Match.syncCodeSigning(type: .adHoc, environment: .staging, isForce: true) + } + // MARK: - Utilities func cleanUpOutputLane() {