diff --git a/.github/workflows/main.yml b/.github/workflows/build-only.yml similarity index 63% rename from .github/workflows/main.yml rename to .github/workflows/build-only.yml index 5a7055792..c23cb30c4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/build-only.yml @@ -3,15 +3,15 @@ name: CI on: push: branches: - - master - - develop - - feature/* - - feature-* - - issue/* - - issue-* + - master + - develop + - feature/* + - feature-* + - issue/* + - issue-* pull_request: branches: - - develop + - develop # macOS environments: https://github.com/actions/virtual-environments/tree/main/images/macos @@ -20,12 +20,12 @@ jobs: name: CI build runs-on: macos-13 steps: - - name: checkout + - name: Repository uses: actions/checkout@v2 - - name: setup - env: + - name: Setup Build Environment + env: NotificationEndpointDebug: ${{ secrets.NotificationEndpointDebug }} NotificationEndpointRelease: ${{ secrets.NotificationEndpointRelease }} run: exec ./.github/scripts/setup.sh - - name: build - run: exec ./.github/scripts/build.sh + - name: Build App + run: bundle exec fastlane ios build_only diff --git a/.github/workflows/deploy-appstore.yml b/.github/workflows/deploy-appstore.yml new file mode 100644 index 000000000..daba7cc7a --- /dev/null +++ b/.github/workflows/deploy-appstore.yml @@ -0,0 +1,40 @@ +name: Deploy App Store +on: + workflow_dispatch: + push: + branches: + - develop + - release* +jobs: + deploy_appstore: + name: Deploy App Store + runs-on: macos-13 + steps: + - name: Install SSH key + uses: webfactory/ssh-agent@v0.5.3 + with: + ssh-private-key: | + ${{ secrets.MATCH_SSH_PRIVATE_KEY }} + - name: Checkout Repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Setup Build Environment + env: + NotificationEndpointDebug: ${{ secrets.NotificationEndpointDebug }} + NotificationEndpointRelease: ${{ secrets.NotificationEndpointRelease }} + run: exec ./.github/scripts/setup.sh + - name: Select required Xcode version + run: sudo xcode-select -switch /Applications/Xcode_15.0.0.app + - name: Deploy App Store + env: + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + ITC_KEY_ID: ${{ secrets.APPSTORE_KEY_ID }} + ITC_ISSUER_ID: ${{ secrets.APPSTORE_ISSUER_ID }} + ITC_KEY: ${{ secrets.APPSTORE_PRIVATE_KEY }} + run: bundle exec fastlane ios deploy_appstore + - name: Tag commit + uses: tvdias/github-tagger@v0.0.1 + with: + repo-token: "${{ secrets.GITHUB_TOKEN }}" + tag: "${{ env.GITHUB_TAG_NAME }}" diff --git a/.github/workflows/develop-build.yml b/.github/workflows/develop-build.yml deleted file mode 100644 index d0019c894..000000000 --- a/.github/workflows/develop-build.yml +++ /dev/null @@ -1,74 +0,0 @@ -name: Build for Develop TestFlight - -on: - push: - branches: - - develop - - release* - - ci-test - -jobs: - build: - name: Build - runs-on: macOS-13 - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Setup - env: - NotificationEndpointDebug: ${{ secrets.NotificationEndpointDebug }} - NotificationEndpointRelease: ${{ secrets.NotificationEndpointRelease }} - run: exec ./.github/scripts/setup.sh - - - name: Install codemagic-cli-tools - uses: actions/setup-python@v4 - with: - python-version: '3.10' - - run: | - pip3 install codemagic-cli-tools - - run: | - codemagic-cli-tools --version || true - - - name: Import Code-Signing Certificates - uses: Apple-Actions/import-codesign-certs@v1 # https://github.com/Apple-Actions/import-codesign-certs - with: - keychain: build-p12 - p12-file-base64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} - p12-password: ${{ secrets.P12_PASSWORD }} - - - name: Download Provisioning Profiles - uses: Apple-Actions/download-provisioning-profiles@v1 # https://github.com/Apple-Actions/download-provisioning-profiles - with: - bundle-id: org.joinmastodon.app - issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }} - api-key-id: ${{ secrets.APPSTORE_KEY_ID }} - api-private-key: ${{ secrets.APPSTORE_PRIVATE_KEY }} - - - name: Build - env: - ENV_APP_ID: ${{ secrets.APP_ID }} - ENV_ISSUER_ID: ${{ secrets.APPSTORE_ISSUER_ID }} - ENV_API_KEY_ID: ${{ secrets.APPSTORE_KEY_ID }} - ENV_API_PRIVATE_KEY: ${{ secrets.APPSTORE_PRIVATE_KEY }} - ENV_API_PRIVATE_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_KEY_BASE64 }} - run: exec ./.github/scripts/build-release.sh - - - name: Upload TestFlight Build - uses: Apple-Actions/upload-testflight-build@master - with: - app-path: .build/Artifacts/Mastodon.ipa/Mastodon.ipa - issuer-id: ${{ secrets.APPSTORE_ISSUER_ID }} - api-key-id: ${{ secrets.APPSTORE_KEY_ID }} - api-private-key: ${{ secrets.APPSTORE_PRIVATE_KEY }} - - - name: Tag commit - uses: tvdias/github-tagger@v0.0.1 - with: - repo-token: "${{ secrets.GITHUB_TOKEN }}" - tag: "${{ env.GITHUB_TAG_NAME }}" - - - name: Clean up keychain and provisioning profile - if: ${{ always() }} - run: | - security delete-keychain build-p12.keychain-db diff --git a/.gitignore b/.gitignore index 742a2c40e..0e4d206bb 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,8 @@ fastlane/report.xml fastlane/Preview.html fastlane/screenshots/**/*.png fastlane/test_output +fastlane/.env +fastlane/devices.txt # Code Injection # After new code Injection tools there's a generated folder /iOSInjectionProject diff --git a/Documentation/Deployment.md b/Documentation/Deployment.md new file mode 100644 index 000000000..5da41510d --- /dev/null +++ b/Documentation/Deployment.md @@ -0,0 +1,21 @@ +# Deployment + +## Your Device + +### As a Mastodon Collaborator WITH access to the Mastodon Apple Developer Program + +To ensure you're able to build the App for your Device please create a `fastlane/devices.txt` and add your device's UDID. +You may use `fastlane/devices.text.example` as a starting point. Please note that fastlane expects you to use tabs in this file. + +After adding your device please run `bundle exec fastlane ios register_devices` to add your device(s) to the Apple Develper Account. +Then run `bundle exec fastlane ios update_certificates` to re-generate the Codesigning Provisioning Profiles. + +You should now be able to run the App using Xcode on your Device. + +### As a Mastodon Contributor WITHOUT access to the Mastodon Apple Developer Program + +To run the App on your Device you'll need to take care of Codesigning yourself by adjusting the App's Codesigning Settings in Xcode to your needs. + +## App Store + +We're using [Fastlane](https://fastlane.tools) to deploy the App to App Store Connect. Please see the [Fastlane README](../fastlane/README.md) on the available commands. diff --git a/Gemfile b/Gemfile index 7ecafafc1..c3ea984b4 100644 --- a/Gemfile +++ b/Gemfile @@ -5,3 +5,7 @@ gem "cocoapods" gem "cocoapods-clean" gem "xcpretty" +# Fastlane +gem "fastlane" +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/Gemfile.lock b/Gemfile.lock index 98539bd5f..1b3792690 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,9 +4,14 @@ GEM CFPropertyList (3.0.6) rexml activesupport (7.0.8) + base64 + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb i18n (>= 1.6, < 2) minitest (>= 5.1) + mutex_m tzinfo (~> 2.0) addressable (2.8.5) public_suffix (>= 2.0.2, < 6.0) @@ -17,12 +22,32 @@ GEM dotenv (~> 2.7) rainbow (~> 3.1.1) yaml (~> 0.2) + artifactory (3.0.15) atomos (0.1.3) + aws-eventstream (1.2.0) + aws-partitions (1.833.0) + aws-sdk-core (3.185.0) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.5) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.72.0) + aws-sdk-core (~> 3, >= 3.184.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.136.0) + aws-sdk-core (~> 3, >= 3.181.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.6) + aws-sigv4 (1.6.0) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + base64 (0.1.1) + bigdecimal (3.1.4) claide (1.1.0) - cocoapods (1.12.1) + cocoapods (1.13.0) addressable (~> 2.8) claide (>= 1.0.2, < 2.0) - cocoapods-core (= 1.12.1) + cocoapods-core (= 1.13.0) cocoapods-deintegrate (>= 1.0.3, < 2.0) cocoapods-downloader (>= 1.6.0, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) @@ -36,9 +61,9 @@ GEM molinillo (~> 0.8.0) nap (~> 1.0) ruby-macho (>= 2.3.0, < 3.0) - xcodeproj (>= 1.21.0, < 2.0) + xcodeproj (>= 1.23.0, < 2.0) cocoapods-clean (0.0.1) - cocoapods-core (1.12.1) + cocoapods-core (1.13.0) activesupport (>= 5.0, < 8) addressable (~> 2.8) algoliasearch (~> 1.0) @@ -57,35 +82,201 @@ GEM nap (>= 0.8, < 2.0) netrc (~> 0.11) cocoapods-try (1.2.0) + colored (1.2) colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) concurrent-ruby (1.2.2) + connection_pool (2.4.1) + declarative (0.0.20) + digest-crc (0.6.5) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) dotenv (2.8.1) + drb (2.1.1) + ruby2_keywords + emoji_regex (3.2.3) escape (0.0.4) ethon (0.16.0) ffi (>= 1.15.0) - ffi (1.15.5) + excon (0.104.0) + faraday (1.10.3) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.0) + faraday (~> 1.0) + fastimage (2.2.7) + fastlane (2.216.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + http-cookie (~> 1.0.5) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (>= 2.0.0, < 3.0.0) + naturally (~> 2.2) + optparse (~> 0.1.1) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (~> 3) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + fastlane-plugin-versioning (0.5.2) + ffi (1.16.3) fourflusher (2.3.1) fuzzy_match (2.0.4) gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.50.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.1) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.19.0) + google-apis-core (>= 0.9.0, < 2.a) + google-cloud-core (1.6.0) + google-cloud-env (~> 1.0) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.3.1) + google-cloud-storage (1.44.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.19.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.8.1) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.5) + domain_name (~> 0.5) httpclient (2.8.3) i18n (1.14.1) concurrent-ruby (~> 1.0) + jmespath (1.6.2) json (2.6.3) + jwt (2.7.1) + mini_magick (4.12.0) + mini_mime (1.1.5) minitest (5.20.0) molinillo (0.8.0) + multi_json (1.15.0) + multipart-post (2.3.0) + mutex_m (0.1.2) nanaimo (0.3.0) nap (1.1.0) + naturally (2.2.1) netrc (0.11.0) + optparse (0.1.1) + os (1.1.4) + plist (3.7.0) public_suffix (4.0.7) rainbow (3.1.1) + rake (13.0.6) + representable (3.2.0) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) rexml (3.2.6) rouge (2.0.7) ruby-macho (2.5.1) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + security (0.1.3) + signet (0.18.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.10) + CFPropertyList + naturally + terminal-notifier (2.0.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.1) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) typhoeus (1.4.0) ethon (>= 0.9.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) - xcodeproj (1.22.0) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) + unicode-display_width (2.5.0) + webrick (1.8.1) + word_wrap (1.0.0) + xcodeproj (1.23.0) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) claide (>= 1.0.2, < 2.0) @@ -94,6 +285,8 @@ GEM rexml (~> 3.2.4) xcpretty (0.3.0) rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) yaml (0.2.1) PLATFORMS @@ -106,6 +299,8 @@ DEPENDENCIES arkana cocoapods cocoapods-clean + fastlane + fastlane-plugin-versioning xcpretty BUNDLED WITH diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index 5de43a801..adb7dc3c4 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -4272,7 +4272,6 @@ CODE_SIGN_ENTITLEMENTS = OpenInActionExtension/OpenInActionExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 5Z4GVSS33P; GENERATE_INFOPLIST_FILE = YES; @@ -4287,6 +4286,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.OpenInActionExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -4300,9 +4300,6 @@ ASSETCATALOG_COMPILER_APPICON_NAME = Icon; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = OpenInActionExtension/OpenInActionExtension.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 5Z4GVSS33P; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = OpenInActionExtension/Info.plist; @@ -4329,10 +4326,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = Icon; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = OpenInActionExtension/OpenInActionExtension.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; DEVELOPMENT_TEAM = 5Z4GVSS33P; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5Z4GVSS33P; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = OpenInActionExtension/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Open using Mastodon"; @@ -4345,6 +4341,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.OpenInActionExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.joinmastodon.app.OpenInActionExtension"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -4358,9 +4355,6 @@ ASSETCATALOG_COMPILER_APPICON_NAME = Icon; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = OpenInActionExtension/OpenInActionExtension.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 5Z4GVSS33P; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = OpenInActionExtension/Info.plist; @@ -4390,7 +4384,6 @@ CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 5Z4GVSS33P; GENERATE_INFOPLIST_FILE = YES; @@ -4405,6 +4398,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.WidgetExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -4419,9 +4413,6 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 5Z4GVSS33P; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = WidgetExtension/Info.plist; @@ -4449,10 +4440,9 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; DEVELOPMENT_TEAM = 5Z4GVSS33P; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5Z4GVSS33P; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = WidgetExtension/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = WidgetExtension; @@ -4465,6 +4455,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.WidgetExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.joinmastodon.app.WidgetExtension"; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; @@ -4479,9 +4470,6 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; CODE_SIGN_ENTITLEMENTS = WidgetExtension/WidgetExtension.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 5Z4GVSS33P; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = WidgetExtension/Info.plist; @@ -4600,9 +4588,12 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "Apple Distribution"; + CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 5Z4GVSS33P; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -4664,10 +4655,9 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; - DEVELOPMENT_TEAM = 5Z4GVSS33P; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5Z4GVSS33P; EXCLUDED_SOURCE_FILE_NAMES = "Mastodon/Resources/Preview\\ Assets.xcassets"; INFOPLIST_FILE = Mastodon/Info.plist; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking"; @@ -4679,6 +4669,7 @@ PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.joinmastodon.app"; SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -4692,6 +4683,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 5889; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4716,6 +4708,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 5889; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4739,6 +4732,7 @@ baseConfigurationReference = 459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */; buildSettings = { CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 5889; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4762,6 +4756,7 @@ baseConfigurationReference = BB482D32A7B9825BF5327C4F /* Pods-Mastodon-MastodonUITests.release.xcconfig */; buildSettings = { CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 5889; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4852,8 +4847,6 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4880,6 +4873,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 5889; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4903,6 +4897,7 @@ baseConfigurationReference = 728DE51ADA27C395C6E1BAB5 /* Pods-Mastodon-MastodonUITests.profile.xcconfig */; buildSettings = { CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 5889; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4926,7 +4921,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4947,7 +4941,6 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4969,7 +4962,6 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4991,6 +4983,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; @@ -5001,6 +4994,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; @@ -5013,8 +5007,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; DEVELOPMENT_TEAM = 5Z4GVSS33P; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -5023,6 +5018,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.joinmastodon.app.MastodonIntent"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; @@ -5035,6 +5031,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; @@ -5045,6 +5042,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; @@ -5057,8 +5055,9 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; DEVELOPMENT_TEAM = 5Z4GVSS33P; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -5067,6 +5066,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.joinmastodon.app.ShareActionExtension"; SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; SWIFT_VERSION = 5.0; @@ -5143,8 +5143,6 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -5170,6 +5168,7 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 5889; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5193,6 +5192,7 @@ baseConfigurationReference = 0827D1674B2523503E8605F6 /* Pods-Mastodon-MastodonUITests.release snapshot.xcconfig */; buildSettings = { CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 5889; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5216,7 +5216,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5237,7 +5236,6 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5259,7 +5257,6 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; - CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -5282,6 +5279,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; @@ -5292,6 +5290,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -5304,8 +5303,9 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; - CODE_SIGN_STYLE = Automatic; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; DEVELOPMENT_TEAM = 5Z4GVSS33P; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -5314,6 +5314,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; PRODUCT_NAME = "$(TARGET_NAME)"; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "match AppStore org.joinmastodon.app.NotificationService"; SKIP_INSTALL = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/Podfile.lock b/Podfile.lock index fd14828b9..ae66ca1b6 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -27,4 +27,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 8c962b3cbb4c225f1e57fb2e4ca03d1f22c45e5e -COCOAPODS: 1.12.1 +COCOAPODS: 1.13.0 diff --git a/README.md b/README.md index f28caf8bd..18756bc6f 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ [![CI](https://github.com/mastodon/mastodon-ios/actions/workflows/main.yml/badge.svg)](https://github.com/mastodon/mastodon-ios/actions/workflows/main.yml) [![Crowdin](https://badges.crowdin.net/mastodon-for-ios/localized.svg)](https://crowdin.com/project/mastodon-for-ios) - Download on the App Store ## Introduction -This is the repository for the official iOS App for Mastodon. You can install it from the App Store now. You can build the app from source and file bug report here. +This is the repository for the official iOS App for Mastodon. You can install it from the App Store now. You can build the app from source and file bug report here. + +Read this blog post for this app to learn more. -Read this blog post for this app to learn more. > [Developing an official iOS app for Mastodon](https://blog.joinmastodon.org/2021/02/developing-an-official-ios-app-for-mastodon/) ## Getting Started @@ -17,6 +17,7 @@ Read this blog post for this app to learn more. - Read the setup guide [here](./Documentation/Setup.md) - About [contributing](./Documentation/CONTRIBUTING.md) - [Documentation folder](./Documentation/) +- [App Store Deployment](./Documentation/Deployment.md) ## Acknowledgments diff --git a/fastlane/Appfile b/fastlane/Appfile new file mode 100644 index 000000000..c55fca302 --- /dev/null +++ b/fastlane/Appfile @@ -0,0 +1,2 @@ +app_identifier("org.joinmastodon.app") +team_id("5Z4GVSS33P") diff --git a/fastlane/Deliverfile b/fastlane/Deliverfile new file mode 100644 index 000000000..5717b1eb3 --- /dev/null +++ b/fastlane/Deliverfile @@ -0,0 +1,3 @@ +force true +app_identifier "org.joinmastodon.app" +precheck_include_in_app_purchases false \ No newline at end of file diff --git a/fastlane/Fastfile b/fastlane/Fastfile new file mode 100644 index 000000000..b1defa95c --- /dev/null +++ b/fastlane/Fastfile @@ -0,0 +1,80 @@ +opt_out_usage +default_platform(:ios) + +$appName = "Mastodon" + +platform :ios do + before_all do |lane| + $bundle_id = "org.joinmastodon.app" + $all_bundle_ids = [ + $bundle_id, + "org.joinmastodon.app.MastodonIntent", + "org.joinmastodon.app.NotificationService", + "org.joinmastodon.app.ShareActionExtension", + "org.joinmastodon.app.OpenInActionExtension", + "org.joinmastodon.app.WidgetExtension" + ] + + lanes_for_building = [:deploy_appstore] + + if lanes_for_building.include?(lane) + app_store_connect_api_key( + key_id: ENV["ITC_KEY_ID"], + issuer_id: ENV["ITC_ISSUER_ID"], + key_content: ENV["ITC_KEY"], + duration: 1200, + in_house: false + ) + ensure_git_status_clean + $version_number = get_version_number_from_xcodeproj(target: $appName) + $build_number = get_build_number() + increment_build_number_in_xcodeproj( + xcodeproj: "#{$appName}.xcodeproj", + build_number: $build_number + ) + end + end + + desc "Update certificates" + lane :update_certificates do + match(type: "development", app_identifier: $all_bundle_ids, force_for_new_devices: true) + match(type: "appstore", app_identifier: $all_bundle_ids, force_for_new_devices: false) + end + + desc "Update devices" + lane :update_devices do + register_devices(devices_file: "./fastlane/devices.txt") + end + + lane :build_only do + xcodebuild( + clean: true, + scheme: "Mastodon", + workspace: "Mastodon.xcworkspace" + ) + end + + desc " Build and deploy the App to App Store Connect & TestFlight" + lane :deploy_appstore do + + if is_ci + create_keychain(name: "temp_keychain", password: "temp_123456", default_keychain: true, unlock: true, timeout: 3600, lock_when_sleeps: false) + match(type: "appstore", app_identifier: $all_bundle_ids, force_for_new_devices: true, readonly: true, keychain_name: "temp_keychain", keychain_password: "temp_123456") + else + match(type: "appstore", app_identifier: $all_bundle_ids, force_for_new_devices: true, readonly: false) + end + + gym(workspace: "#{$appName}.xcworkspace", + scheme: "#{$appName}", + clean: true, + export_method: "app-store", + export_xcargs: "-allowProvisioningUpdates") + deliver(app_identifier: $bundle_id, skip_screenshots: true, skip_metadata: true) + + sh("echo \"GITHUB_TAG_NAME=#{$version_number}-#{$build_number}\" >> $GITHUB_ENV") + end +end + +def get_build_number + sh("git rev-list --count HEAD").chomp +end diff --git a/fastlane/Matchfile b/fastlane/Matchfile new file mode 100644 index 000000000..8ba507988 --- /dev/null +++ b/fastlane/Matchfile @@ -0,0 +1,14 @@ +git_url("git@github.com:mastodon/mastodon-ios-match.git") +storage_mode("git") +git_branch("main") +type("appstore") # The default type, can be: appstore, adhoc, enterprise or development + +app_identifier([ + "org.joinmastodon.app", + "org.joinmastodon.app.MastodonIntent", + "org.joinmastodon.app.NotificationService", + "org.joinmastodon.app.ShareActionExtension", + "org.joinmastodon.app.OpenInActionExtension", + "org.joinmastodon.app.WidgetExtension" +]) +# username("fastlane@joinmastodon.org") diff --git a/fastlane/Pluginfile b/fastlane/Pluginfile new file mode 100644 index 000000000..87578f80a --- /dev/null +++ b/fastlane/Pluginfile @@ -0,0 +1,5 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-versioning' diff --git a/fastlane/README.md b/fastlane/README.md new file mode 100644 index 000000000..87c6dfe1a --- /dev/null +++ b/fastlane/README.md @@ -0,0 +1,56 @@ +fastlane documentation +---- + +# Installation + +Make sure you have the latest version of the Xcode command line tools installed: + +```sh +xcode-select --install +``` + +For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane) + +# Available Actions + +## iOS + +### ios update_certificates + +```sh +[bundle exec] fastlane ios update_certificates +``` + +Update certificates + +### ios update_devices + +```sh +[bundle exec] fastlane ios update_devices +``` + +Update devices + +### ios build_only + +```sh +[bundle exec] fastlane ios build_only +``` + + + +### ios deploy_appstore + +```sh +[bundle exec] fastlane ios deploy_appstore +``` + + Build and deploy the App to App Store Connect & TestFlight + +---- + +This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. + +More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools). + +The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools). diff --git a/fastlane/devices.txt.example b/fastlane/devices.txt.example new file mode 100644 index 000000000..16e1b77b9 --- /dev/null +++ b/fastlane/devices.txt.example @@ -0,0 +1,2 @@ +Device ID Device Name Device Platform +00000000-0000000000000000 Your-Device-Name ios \ No newline at end of file