From 90233b6a211c107d9d8d92f76289a4fe0c1646b0 Mon Sep 17 00:00:00 2001 From: James Magahern Date: Mon, 27 Jul 2026 17:30:02 -0700 Subject: [PATCH] Simplify TestFlight automation --- .env.example | 17 +-- .gitea/workflows/testflight.yml | 34 ++--- Gemfile | 2 +- Gemfile.lock | 137 ++++++++++--------- README.md | 4 +- SBrowser.xcodeproj/project.pbxproj | 8 +- fastlane/Appfile | 2 + fastlane/Fastfile | 202 ++++------------------------- fastlane/Matchfile | 7 + 9 files changed, 134 insertions(+), 279 deletions(-) create mode 100644 fastlane/Appfile create mode 100644 fastlane/Matchfile diff --git a/.env.example b/.env.example index 2770ad8..5ca8e90 100644 --- a/.env.example +++ b/.env.example @@ -1,16 +1,5 @@ -FASTLANE_SKIP_UPDATE_CHECK=1 -FASTLANE_HIDE_CHANGELOG=1 -FASTLANE_TEAM_ID=DQQH5H6GBD - -APP_STORE_CONNECT_KEY_ID= -APP_STORE_CONNECT_ISSUER_ID= -APP_STORE_CONNECT_KEY_CONTENT= - -MATCH_GIT_URL= +ASC_KEY_ID= +ASC_ISSUER_ID= +ASC_KEY= MATCH_PASSWORD= MATCH_GIT_BASIC_AUTHORIZATION= -MATCH_GIT_BRANCH=master - -ATTRACTOR_PROVISIONING_PROFILE_SPECIFIER=Attractor AppStore CI -ATTRACTOR_VERSION_TAG= -ATTRACTOR_BUILD_NUMBER= diff --git a/.gitea/workflows/testflight.yml b/.gitea/workflows/testflight.yml index df2c3da..7c9c924 100644 --- a/.gitea/workflows/testflight.yml +++ b/.gitea/workflows/testflight.yml @@ -1,7 +1,6 @@ name: TestFlight on: - workflow_dispatch: push: tags: - "release/ios/v*" @@ -9,37 +8,28 @@ on: jobs: testflight: - runs-on: xcode - defaults: - run: - shell: bash + name: Build and upload + runs-on: macos-arm64 + timeout-minutes: 90 steps: - - name: Checkout + - name: Check out the release tag uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Setup Ruby + - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: "3.1.7" + ruby-version: "3.3.11" bundler-cache: true - - name: Upload to TestFlight + - name: Build and upload to TestFlight env: - HOME: /var/lib/act_runner - APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} - APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} - APP_STORE_CONNECT_KEY_CONTENT: ${{ secrets.APP_STORE_CONNECT_KEY_CONTENT }} + ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }} + ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }} + ASC_KEY: ${{ secrets.ASC_KEY }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }} - ATTRACTOR_VERSION_TAG: ${{ github.ref_name }} + CI: "true" FASTLANE_SKIP_UPDATE_CHECK: "1" FASTLANE_HIDE_CHANGELOG: "1" - FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: "120" - run: | - export PATH="/Users/runner/hostedtoolcache/Ruby/3.1.7/arm64/bin:${PATH}" - ruby --version - bundle exec fastlane ios beta + run: bundle exec fastlane ios beta diff --git a/Gemfile b/Gemfile index 7a118b4..0b11579 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,3 @@ source "https://rubygems.org" -gem "fastlane" +gem "fastlane", "2.237.0" diff --git a/Gemfile.lock b/Gemfile.lock index 4130921..f5ad616 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,46 +1,49 @@ GEM remote: https://rubygems.org/ specs: - CFPropertyList (3.0.9) + CFPropertyList (3.0.8) abbrev (0.1.2) addressable (2.9.0) public_suffix (>= 2.0.2, < 8.0) artifactory (3.0.17) atomos (0.1.3) - aws-eventstream (1.3.2) - aws-partitions (1.1109.0) - aws-sdk-core (3.224.1) + aws-eventstream (1.4.0) + aws-partitions (1.1274.0) + aws-sdk-core (3.254.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) base64 + bigdecimal jmespath (~> 1, >= 1.6.1) logger - aws-sdk-kms (1.101.0) - aws-sdk-core (~> 3, >= 3.216.0) + aws-sdk-kms (1.130.0) + aws-sdk-core (~> 3, >= 3.254.0) aws-sigv4 (~> 1.5) - aws-sdk-s3 (1.188.0) - aws-sdk-core (~> 3, >= 3.224.1) + aws-sdk-s3 (1.228.1) + aws-sdk-core (~> 3, >= 3.254.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.5) - aws-sigv4 (1.11.0) + aws-sigv4 (1.12.1) aws-eventstream (~> 1, >= 1.0.2) babosa (1.0.4) - base64 (0.2.0) + base64 (0.3.0) + benchmark (0.5.0) + bigdecimal (4.1.2) claide (1.1.0) colored (1.2) colored2 (3.1.2) commander (4.6.0) highline (~> 2.0.0) - csv (3.3.5) + csv (3.3.6) declarative (0.0.20) digest-crc (0.7.0) rake (>= 12.0.0, < 14.0.0) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) + domain_name (0.6.20240107) dotenv (2.8.1) emoji_regex (3.2.3) - excon (0.109.0) + excon (1.6.0) + logger faraday (1.10.6) faraday-em_http (~> 1.0) faraday-em_synchrony (~> 1.0) @@ -70,42 +73,45 @@ GEM faraday_middleware (1.2.1) faraday (~> 1.0) fastimage (2.4.1) - fastlane (2.230.0) - CFPropertyList (>= 2.3, < 4.0.0) - abbrev (~> 0.1.2) - addressable (>= 2.8, < 3.0.0) + fastlane (2.237.0) + CFPropertyList (>= 2.3, < 5.0.0) + abbrev (~> 0.1) + addressable (>= 2.9.0, < 3.0.0) artifactory (~> 3.0) - aws-sdk-s3 (~> 1.0) + aws-sdk-s3 (~> 1.197) babosa (>= 1.0.3, < 2.0.0) - base64 (~> 0.2.0) - bundler (>= 1.12.0, < 3.0.0) + base64 (~> 0.2) + benchmark (>= 0.1.0) + bundler (>= 2.4.0, < 5.0.0) colored (~> 1.2) commander (~> 4.6) csv (~> 3.3) dotenv (>= 2.1.1, < 3.0.0) emoji_regex (>= 0.1, < 4.0) - excon (>= 0.71.0, < 1.0.0) + excon (>= 0.71.0, < 2.0.0) faraday (~> 1.0) faraday-cookie_jar (~> 0.0.6) faraday_middleware (~> 1.0) fastimage (>= 2.1.0, < 3.0.0) - fastlane-sirp (>= 1.0.0) + fastlane-sirp (>= 1.1.0) gh_inspector (>= 1.1.2, < 2.0.0) google-apis-androidpublisher_v3 (~> 0.3) google-apis-playcustomapp_v1 (~> 0.1) - google-cloud-env (>= 1.6.0, < 2.0.0) + google-cloud-env (>= 1.6.0, < 2.3.0) google-cloud-storage (~> 1.31) highline (~> 2.0) http-cookie (~> 1.0.5) json (< 3.0.0) - jwt (>= 2.1.0, < 3) + jwt (>= 2.10.3, < 4) logger (>= 1.6, < 2.0) mini_magick (>= 4.9.4, < 5.0.0) + multi_json (~> 1.12) multipart-post (>= 2.0.0, < 3.0.0) - mutex_m (~> 0.3.0) + mutex_m (~> 0.3) naturally (~> 2.2) - nkf (~> 0.2.0) + nkf (~> 0.2) optparse (>= 0.1.1, < 1.0.0) + ostruct (>= 0.1.0) plist (>= 3.1.0, < 4.0.0) rubyzip (>= 2.0.0, < 3.0.0) security (= 0.1.5) @@ -120,41 +126,46 @@ GEM xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) fastlane-sirp (1.1.0) gh_inspector (1.1.3) - google-apis-androidpublisher_v3 (0.54.0) - google-apis-core (>= 0.11.0, < 2.a) - google-apis-core (0.11.3) + google-apis-androidpublisher_v3 (0.106.0) + google-apis-core (>= 0.15.0, < 2.a) + google-apis-core (0.18.0) addressable (~> 2.5, >= 2.5.1) - googleauth (>= 0.16.2, < 2.a) - httpclient (>= 2.8.1, < 3.a) + googleauth (~> 1.9) + httpclient (>= 2.8.3, < 3.a) mini_mime (~> 1.0) + mutex_m representable (~> 3.0) retriable (>= 2.0, < 4.a) - rexml - 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.29.0) - google-apis-core (>= 0.11.0, < 2.a) - google-cloud-core (1.6.1) + google-apis-iamcredentials_v1 (0.28.0) + google-apis-core (>= 0.15.0, < 2.a) + google-apis-playcustomapp_v1 (0.18.0) + google-apis-core (>= 0.15.0, < 2.a) + google-apis-storage_v1 (0.65.0) + google-apis-core (>= 0.15.0, < 2.a) + google-cloud-core (1.9.0) google-cloud-env (>= 1.0, < 3.a) 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.45.0) + google-cloud-env (2.2.2) + base64 (~> 0.2) + faraday (>= 1.0, < 3.a) + google-cloud-errors (1.7.0) + google-cloud-storage (1.62.0) addressable (~> 2.8) digest-crc (~> 0.4) - google-apis-iamcredentials_v1 (~> 0.1) - google-apis-storage_v1 (~> 0.29.0) + google-apis-core (>= 0.18, < 2) + google-apis-iamcredentials_v1 (~> 0.18) + google-apis-storage_v1 (>= 0.42) google-cloud-core (~> 1.6) - googleauth (>= 0.16.2, < 2.a) + googleauth (~> 1.9) mini_mime (~> 1.0) - googleauth (1.8.1) - faraday (>= 0.17.3, < 3.a) - jwt (>= 1.4, < 3.0) - multi_json (~> 1.11) + google-logging-utils (0.2.0) + googleauth (1.17.2) + faraday (>= 1.0, < 3.a) + google-cloud-env (~> 2.2) + google-logging-utils (~> 0.1) + jwt (>= 1.4, < 4.0) os (>= 0.9, < 2.0) + pstore (~> 0.1) signet (>= 0.16, < 2.a) highline (2.0.3) http-cookie (1.0.8) @@ -162,22 +173,24 @@ GEM httpclient (2.9.0) mutex_m jmespath (1.6.2) - json (2.7.6) - jwt (2.10.3) + json (2.21.1) + jwt (3.2.0) base64 logger (1.7.0) mini_magick (4.13.2) mini_mime (1.1.5) - multi_json (1.15.0) + multi_json (1.21.1) multipart-post (2.4.1) mutex_m (0.3.0) nanaimo (0.4.0) naturally (2.3.0) - nkf (0.2.0) + nkf (0.3.0) optparse (0.8.1) os (1.1.4) + ostruct (0.6.3) plist (3.7.2) - public_suffix (5.1.1) + pstore (0.2.1) + public_suffix (7.0.5) rake (13.4.2) representable (3.2.0) declarative (< 0.1.0) @@ -189,11 +202,10 @@ GEM ruby2_keywords (0.0.5) rubyzip (2.4.1) security (0.1.5) - signet (0.18.0) + signet (0.22.0) addressable (~> 2.8) faraday (>= 0.17.5, < 3.a) - jwt (>= 1.5, < 3.0) - multi_json (~> 1.10) + jwt (>= 1.5, < 4.0) simctl (1.6.10) CFPropertyList naturally @@ -206,15 +218,16 @@ GEM tty-spinner (0.9.3) tty-cursor (~> 0.7) uber (0.1.0) - unf (0.2.0) unicode-display_width (2.6.0) word_wrap (1.0.0) - xcodeproj (1.27.0) + xcodeproj (1.28.1) CFPropertyList (>= 2.3.3, < 4.0) atomos (~> 0.1.3) + base64 claide (>= 1.0.2, < 2.0) colored2 (~> 3.1) nanaimo (~> 0.4.0) + nkf rexml (>= 3.3.6, < 4.0) xcpretty (0.4.1) rouge (~> 3.28.0) @@ -225,7 +238,7 @@ PLATFORMS ruby DEPENDENCIES - fastlane + fastlane (= 2.237.0) BUNDLED WITH 2.5.23 diff --git a/README.md b/README.md index cb22a30..6c416ae 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,6 @@ Attractor operates in five "security modes": TestFlight deployment is handled by Fastlane and the Gitea workflow at `.gitea/workflows/testflight.yml`. -Required Gitea secrets match the local `.env.example`: `APP_STORE_CONNECT_KEY_ID`, `APP_STORE_CONNECT_ISSUER_ID`, `APP_STORE_CONNECT_KEY_CONTENT`, `MATCH_GIT_URL`, `MATCH_PASSWORD`, and `MATCH_GIT_BASIC_AUTHORIZATION`. +Required Gitea secrets match the local `.env.example`: `ASC_KEY_ID`, `ASC_ISSUER_ID`, `ASC_KEY`, `MATCH_PASSWORD`, and `MATCH_GIT_BASIC_AUTHORIZATION`. -Push a tag like `release/ios/v4.2` or `Attractor-4.2` to build and upload to TestFlight. To prepare signing assets locally, run `bundle exec fastlane ios setup_signing`; to upload manually, run `bundle exec fastlane ios beta`. +Push a tag like `release/ios/v4.2` or `Attractor-4.2` to build and upload to TestFlight. diff --git a/SBrowser.xcodeproj/project.pbxproj b/SBrowser.xcodeproj/project.pbxproj index 50f9656..c615d1d 100644 --- a/SBrowser.xcodeproj/project.pbxproj +++ b/SBrowser.xcodeproj/project.pbxproj @@ -823,11 +823,11 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements"; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = "Apple Distribution"; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 6; DEAD_CODE_STRIPPING = YES; - DEVELOPMENT_TEAM = 3SJALV9BQ7; + DEVELOPMENT_TEAM = DQQH5H6GBD; INFOPLIST_FILE = "App/Supporting Files/Info.plist"; INFOPLIST_KEY_CFBundleDisplayName = Attractor; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; @@ -839,7 +839,7 @@ MARKETING_VERSION = 4.1; PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.attractor; PRODUCT_NAME = Attractor; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE_SPECIFIER = "Attractor AppStore CI"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; diff --git a/fastlane/Appfile b/fastlane/Appfile new file mode 100644 index 0000000..25cf6ad --- /dev/null +++ b/fastlane/Appfile @@ -0,0 +1,2 @@ +app_identifier("net.buzzert.attractor") +team_id("DQQH5H6GBD") diff --git a/fastlane/Fastfile b/fastlane/Fastfile index fa0e6fe..1279be5 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -1,186 +1,40 @@ -require "shellwords" -require "xcodeproj" - default_platform(:ios) -APP_IDENTIFIER = "net.buzzert.attractor" -SCHEME = "Attractor" -TARGET_NAME = "App" -TEAM_ID = ENV["FASTLANE_TEAM_ID"].to_s.strip.empty? ? "DQQH5H6GBD" : ENV["FASTLANE_TEAM_ID"] -PROFILE_NAME = ENV["ATTRACTOR_PROVISIONING_PROFILE_SPECIFIER"].to_s.strip.empty? ? "Attractor AppStore CI" : ENV["ATTRACTOR_PROVISIONING_PROFILE_SPECIFIER"] -CI_KEYCHAIN_NAME = "attractor_ci_keychain" -CI_KEYCHAIN_PASSWORD = "attractor-ci-keychain-password" -CI_KEYCHAIN_DB_PATH = File.expand_path("~/Library/Keychains/#{CI_KEYCHAIN_NAME}-db") -PROJECT_FILE = File.expand_path("../SBrowser.xcodeproj", __dir__) - -def present?(value) - !value.to_s.strip.empty? -end - -def ci? - present?(ENV["CI"]) -end - -def version_from_tag(tag) - patterns = [ - %r{\Arelease/ios/v(\d+(?:\.\d+){1,2})\z}, - %r{\AAttractor-(\d+(?:\.\d+){1,2})\z}, - %r{\Av(\d+(?:\.\d+){1,2})\z} - ] - - patterns.each do |pattern| - match = tag.to_s.match(pattern) - return match[1] if match - end - - nil -end - -def release_version - candidates = [ - ENV["ATTRACTOR_VERSION_TAG"], - ENV["GITHUB_REF_NAME"], - ENV["GITHUB_REF"].to_s.sub(%r{\Arefs/tags/}, "") - ] - - candidates.each do |tag| - version = version_from_tag(tag) - return version if version - end - - latest_tag = sh("git describe --tags --abbrev=0").strip - version = version_from_tag(latest_tag) - return version if version - - candidates << latest_tag - UI.user_error!("Release tag must look like release/ios/v4.1, Attractor-4.1, or v4.1; got #{candidates.compact.inspect}") -end - -# App Store Connect requires CFBundleVersion to be unique and strictly -# increasing app-wide. Attractor already has historical builds, so use a UTC -# timestamp by default instead of assuming a fresh CI run number is high enough. -def build_number - value = ENV["ATTRACTOR_BUILD_NUMBER"] - value = Time.now.utc.strftime("%Y%m%d%H%M%S") unless present?(value) - - unless value.to_s.match?(/\A\d+\z/) - UI.user_error!("Build number must be numeric; got #{value.inspect}") - end - - value.to_s -end - -def stamp_project_versions(version:, build:) - project = Xcodeproj::Project.open(PROJECT_FILE) - target = project.targets.find { |candidate| candidate.name == TARGET_NAME } - UI.user_error!("Could not find target #{TARGET_NAME.inspect} in #{PROJECT_FILE}") unless target - - target.build_configurations.each do |configuration| - configuration.build_settings["MARKETING_VERSION"] = version - configuration.build_settings["CURRENT_PROJECT_VERSION"] = build - end - - project.save -end - platform :ios do - private_lane :app_store_api_key do - app_store_connect_api_key( - key_id: ENV.fetch("APP_STORE_CONNECT_KEY_ID"), - issuer_id: ENV.fetch("APP_STORE_CONNECT_ISSUER_ID"), - key_content: ENV.fetch("APP_STORE_CONNECT_KEY_CONTENT"), + desc "Build a release tag and upload it to TestFlight" + lane :beta do + setup_ci + + match(type: "appstore") + + tag = ENV.fetch("GITHUB_REF_NAME") + version = tag[%r{\A(?:release/ios/v|Attractor-)(\d+(?:\.\d+){1,2})\z}, 1] + UI.user_error!("Expected a tag like release/ios/v4.2 or Attractor-4.2; got #{tag.inspect}") unless version + + build_number = ENV.fetch("GITHUB_RUN_NUMBER") + UI.user_error!("GITHUB_RUN_NUMBER must be a positive integer") unless build_number.match?(/\A[1-9]\d*\z/) + + update_info_plist( + plist_path: "App/Supporting Files/Info.plist", + block: proc do |plist| + plist["CFBundleShortVersionString"] = version + plist["CFBundleVersion"] = build_number + end + ) + + api_key = app_store_connect_api_key( + key_id: ENV.fetch("ASC_KEY_ID"), + issuer_id: ENV.fetch("ASC_ISSUER_ID"), + key_content: ENV.fetch("ASC_KEY"), is_key_content_base64: true ) - end - # CI signs headlessly, so match needs a fresh unlocked keychain to import - # into. codesign resolves identities through the user keychain search - # list (first match wins; the --keychain flag does not restrict the - # lookup), and other projects' keychains on this runner hold the same - # identity but are usually locked — so ours must come first. delete_keychain - # in the beta lane's ensure removes both the keychain and its search-list - # entry, which also keeps our (later locked) copy from shadowing those - # other projects. - private_lane :prepare_ci_keychain do - next unless ci? - - delete_keychain(name: CI_KEYCHAIN_NAME) if File.file?(CI_KEYCHAIN_DB_PATH) - create_keychain( - name: CI_KEYCHAIN_NAME, - password: CI_KEYCHAIN_PASSWORD, - unlock: true, - timeout: 3600, - add_to_search_list: false - ) - - others = sh("security list-keychains -d user", log: false) - .scan(/"([^"]+)"/) - .flatten - .reject { |path| path.include?(CI_KEYCHAIN_NAME) } - sh("security list-keychains -d user -s #{([CI_KEYCHAIN_DB_PATH] + others).shelljoin}") - - ENV["MATCH_KEYCHAIN_NAME"] = CI_KEYCHAIN_NAME - ENV["MATCH_KEYCHAIN_PASSWORD"] = CI_KEYCHAIN_PASSWORD - end - - private_lane :sync_signing do |options| - match( - type: "appstore", - readonly: options.fetch(:readonly), - app_identifier: APP_IDENTIFIER, - team_id: TEAM_ID, - profile_name: PROFILE_NAME, - git_url: ENV.fetch("MATCH_GIT_URL"), - git_branch: ENV.fetch("MATCH_GIT_BRANCH", "master"), - git_full_name: "Attractor Release Bot", - git_user_email: "james.magahern@me.com", - api_key: options.fetch(:api_key) - ) - end - - desc "Create or update match signing assets" - lane :setup_signing do - sync_signing(api_key: app_store_api_key, readonly: false) - end - - desc "Build and upload to TestFlight" - lane :beta do - prepare_ci_keychain - - api_key = app_store_api_key - version = release_version - build = build_number - - stamp_project_versions(version: version, build: build) - - sync_signing(api_key: api_key, readonly: true) - - build_app( - project: PROJECT_FILE, - scheme: SCHEME, - destination: "generic/platform=iOS", - export_method: "app-store", - codesigning_identity: "Apple Distribution", - xcargs: [ - "DEVELOPMENT_TEAM=#{TEAM_ID.shellescape}", - "CODE_SIGN_STYLE=Manual", - "CODE_SIGN_IDENTITY=Apple\\ Distribution", - "PROVISIONING_PROFILE_SPECIFIER=#{PROFILE_NAME.shellescape}" - ].join(" "), - export_options: { - signingStyle: "manual", - teamID: TEAM_ID, - provisioningProfiles: { - APP_IDENTIFIER => PROFILE_NAME - } - } - ) + build_app(scheme: "Attractor") upload_to_testflight( api_key: api_key, - skip_waiting_for_build_processing: true + skip_waiting_for_build_processing: true, + uses_non_exempt_encryption: false ) - ensure - delete_keychain(name: CI_KEYCHAIN_NAME) if ci? && File.file?(CI_KEYCHAIN_DB_PATH) end end diff --git a/fastlane/Matchfile b/fastlane/Matchfile new file mode 100644 index 0000000..3426da5 --- /dev/null +++ b/fastlane/Matchfile @@ -0,0 +1,7 @@ +git_url("https://code.buzzert.dev/buzzert/fastlane-match.git") +storage_mode("git") +type("appstore") + +app_identifier(["net.buzzert.attractor"]) +team_id("DQQH5H6GBD") +profile_name("Attractor AppStore CI")