fastlane icon indicating copy to clipboard operation
fastlane copied to clipboard

[match] Imported tvOS provisioning profile generated name does not match the one expected when retrieving profiles for building the tvOS app

Open aureliencolas opened this issue 1 year ago • 0 comments

New Issue Checklist

Issue Description

When importing the main tvOS app provisioning profile to bitbucket (using fastlane match command), the profile generated name does not contain the usual _tvOS suffix despite providing the parameter platform tvos. Hence, when building the app, match looks for a profile with the _tvOS suffix and does not find it. Moreover, the iOS app provisioning profile gets replaced by the tvOS app one. Generated name for the tvOS app: AppStore_lu.<bundleID>.mobileprovision Name expected by match when building the tvOS app: AppStore_lu.<bundleID>_tvos.mobileprovision

Full error message:

[09:40:03]: No matching provisioning profiles found for 'AppStore_lu.<bundleID>_tvos.mobileprovision'
[09:40:03]: A new one cannot be created because you enabled `readonly`
[09:40:03]: Provisioning profiles in your repo for type `appstore`:
[09:40:03]: - 'AppStore_lu.<bundleID>.notificationservice.mobileprovision'
[09:40:03]: - 'AppStore_lu.<bundleID>.tvtopshelf.mobileprovision'
[09:40:03]: - 'AppStore_lu.<bundleID>.mobileprovision'

Several notes:

  • When using match update with other developer accounts I have admin access to, the main tvOS app provisioning profile name generated by match contains the _tvOS suffix. The issue only occurs when importing profiles using match import.
  • The _tvOS suffix is also missing in the TV Top Shelp tvOS app extension provisioning profile generated name (should be 'AppStore_lu.<bundleID>.tvtopshelf_tvOS.mobileprovision')
  • Note sure I can safely share the provisioning profiles here so I don't but they are indeed tvOS platform profiles
Command executed

bundle exec fastlane match import --type appstore --skip_provisioning_profiles true --clone_branch_directly true --git_branch XXXXXXXX --team_id XXXXXXXX --app_identifier XXXXXXXX --platform tvos

Complete output when running fastlane, including the stack trace and command used
 [✔] 🚀 
Fastfile:77: warning: already initialized constant Spaceship::ConnectAPI::App::ESSENTIAL_INCLUDES
/Users/aureliencolas/.rubies/ruby-3.2.1/lib/ruby/gems/3.2.0/gems/fastlane-2.220.0/spaceship/lib/spaceship/connect_api/models/app.rb:61: warning: previous definition of ESSENTIAL_INCLUDES was here
[09:39:56]: ------------------------------
[09:39:56]: --- Step: default_platform ---
[09:39:56]: ------------------------------
Available session is not valid anymore. Continuing with normal login.
[09:40:00]: Driving the lane 'ios deploy_app' 🚀
[09:40:00]: -------------------
[09:40:00]: --- Step: match ---
[09:40:00]: -------------------
[09:40:00]: Successfully loaded '/Users/aureliencolas/Documents/netgem/repos/videofutur-ios-swift/fastlane/Matchfile' 📄

+----------------------------------------------------------+ | Detected Values from './fastlane/Matchfile' | +--------------+-------------------------------------------+ | git_url | [email protected]:netgem/ios-fastlane.git | | storage_mode | git | | type | appstore | +--------------+-------------------------------------------+

+------------------------------------------------------------------------------------+ | Summary for match 2.220.0 | +----------------------------------------+-------------------------------------------+ | type | appstore | | git_branch | XXXXXXXX | | clone_branch_directly | true | | app_identifier | ["XXXXXXXX"] | | platform | tvos | | readonly | true | | generate_apple_certs | true | | skip_provisioning_profiles | false | | username | XXXXXXXX | | storage_mode | git | | git_url | [email protected]:xxxxxxxxx.git | | shallow_clone | false | | skip_google_cloud_account_confirmation | false | | s3_skip_encryption | false | | gitlab_host | https://gitlab.com | | keychain_name | login.keychain | | force | false | | force_for_new_devices | false | | include_mac_in_profiles | false | | include_all_certificates | false | | force_for_new_certificates | false | | skip_confirmation | false | | safe_remove_certs | false | | skip_docs | false | | derive_catalyst_app_identifier | false | | fail_on_name_taken | false | | skip_certificate_matching | false | | skip_set_partition_list | false | | verbose | false | +----------------------------------------+-------------------------------------------+

[09:40:00]: Cloning remote git repo... [09:40:03]: Checking out branch XXXXXXXX... [09:40:03]: 🔓 Successfully decrypted certificates repo [09:40:03]: Installing certificate...

+-------------------------------------------------------------------------------------+ | Installed Certificate | +-------------------+-----------------------------------------------------------------+ | User ID | XXXXXXXX | | Common Name | iPhone Distribution: POST Luxembourg Etabl. Public (XXXXXXXX) | | Organisation Unit | XXXXXXXX | | Organisation | POST Luxembourg Etabl. Public | | Country | LU | | Start Datetime | 2023-08-07 14:29:30 UTC | | End Datetime | 2024-08-06 14:29:29 UTC | +-------------------+-----------------------------------------------------------------+

[09:40:03]: No matching provisioning profiles found for 'AppStore_lu.<bundleID>_tvos.mobileprovision' [09:40:03]: A new one cannot be created because you enabled readonly [09:40:03]: Provisioning profiles in your repo for type appstore: [09:40:03]: - 'AppStore_lu.<bundleID>.notificationservice.mobileprovision' [09:40:03]: - 'AppStore_lu.<bundleID>.tvtopshelf.mobileprovision' [09:40:03]: - 'AppStore_lu.<bundleID>.mobileprovision' [09:40:03]: If you are certain that a profile should exist, double-check the recent changes to your match repository +-----------------------------------+ | Lane Context | +------------------+----------------+ | DEFAULT_PLATFORM | ios | | PLATFORM_NAME | ios | | LANE_NAME | ios deploy_app | +------------------+----------------+ [09:40:03]: No matching provisioning profiles found and cannot create a new one because you enabled readonly. Check the output above for more information.

+---------------------------------------+ | fastlane summary | +------+------------------+-------------+ | Step | Action | Time (in s) | +------+------------------+-------------+ | 1 | default_platform | 0 | | 💥 | match | 3 | +------+------------------+-------------+

[09:40:03]: fastlane finished with errors

[!] No matching provisioning profiles found and cannot create a new one because you enabled readonly. Check the output above for more information.

Environment

 
🚫 fastlane environment 🚫

Stack

Key Value
OS 14.5
Ruby 3.2.1
Bundler? true
Git git version 2.39.3 (Apple Git-146)
Installation Source ~/.rubies/ruby-3.2.1/bin/fastlane
Host macOS 14.5 (23F79)
Ruby Lib Dir ~/.rubies/ruby-3.2.1/lib
OpenSSL Version OpenSSL 1.1.1t 7 Feb 2023
Is contained false
Is homebrew false
Is installed via Fabric.app false
Xcode Path /Applications/Xcode.app/Contents/Developer/
Xcode Version 15.4
Swift Version 5.10

System Locale

Error
No Locale with UTF8 found 🚫

fastlane files:

`./Fastfile`
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
#     https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
#     https://docs.fastlane.tools/plugins/available-plugins
#

# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane

# Launch a lane with:
# bundle exec fastlane <lane>

all_configs = [
]
custom_configs = [
]
teams_config = {
}
match_verbose = false

require "spaceship"
Spaceship::ConnectAPI::App.const_set('ESSENTIAL_INCLUDES', 'appStoreVersions')

default_platform(:ios)

# IMPORTANT: Increase the default timeout to 30s as the packages dependencies may take much longer to resolve than the default timeout (which could make the build fail)
ENV['FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT'] = "30"

def build(scheme, flavor, build_number, platform)
    UI.message "Building #{flavor} #{platform} ##{build_number}"
    output_name = "#{flavor}.ipa"
    output_directory = "./fastlane/builds/#{build_number}/#{platform}"
    build_app(scheme: scheme, output_directory: output_directory, output_name: output_name, clean: true, silent: false, xcargs: "-allowProvisioningUpdates")
    return "#{output_directory}/#{output_name}"
end

def to_testflight(ipa, team_name)
    UI.message "Uploading #{ipa} to the App Store with team: #{team_name}"
    # TODO: provide a "changelog"
    upload_to_testflight(ipa: ipa, team_name: team_name, skip_waiting_for_build_processing: true)
end

def check_valid_scheme(scheme)
    schemes = Xcodeproj::Project.schemes('../videofutur/videofutur.xcodeproj')
    valid = schemes.include? scheme
    if !valid
        UI.error "Invalid schem <#{scheme}>"
        UI.error "Valid schemes: #{schemes.join(", ")}"
    end
    return valid
end

# Gets the bundle identifier for the given scheme
def getSchemeInfo(scheme)
    project = Xcodeproj::Project.open('../videofutur/videofutur.xcodeproj')
    target = project.native_targets.find { |target| target.name == scheme }
    if target == nil
        UI.error "Invalid scheme <#{scheme}>"
        UI.error "Valid schemes: #{project.native_targets.map { |target| target.name }.join(", ")}"
        return
    end
    build_configuration = target.build_configurations.first
    bundle = build_configuration.resolve_build_setting('PRODUCT_BUNDLE_IDENTIFIER')
    portal_team_id = build_configuration.resolve_build_setting('DEVELOPMENT_TEAM')
    flavor = build_configuration.resolve_build_setting('FLAVOR')
    # the platform defautl values are not considered yet so SDKROOT is not resolved
    # (https://www.rubydoc.info/gems/xcodeproj/Xcodeproj%2FProject%2FObject%2FAbstractTarget:resolved_build_setting)
    platform = scheme == "Generic_iOS" ? "ios" : "tvos"
    build_number = build_configuration.resolve_build_setting('CURRENT_PROJECT_VERSION')

    return bundle, portal_team_id, flavor, platform, build_number
end

def teams_map
    map = {}
    client = Spaceship::Portal.login()
    client.teams.each do |team|
        map[team['teamId']] = team['name']
    end
    return map
end
teams_map = teams_map()


platform :ios do
    desc "Run Swiftlint"
    lane :swiftlintReport do
        swiftlint(config_file: "./fastlane/swiftlintrules.yml")
    end

    lane :deploy_app do |options|
        scheme = options[:scheme]
    
        # if the flavor is provided, fetch its files into the Generic target
        flavor = options[:flavor]
        if (scheme == "Generic_iOS" || scheme == "Generic_tvOS") && flavor != nil
            UI.message "Setup Generic flavor: #{flavor}"
            sh("../videofutur/Scripts/setFlavor.sh", flavor)
            #UI.message "Wait a bit to let the packages refresh end"
            #sleep(20)
        end

        # get the bundle identifier and Developer Portal team id
        bundle, portal_team_id, flavor, platform, build_number = getSchemeInfo(scheme)
        if bundle == nil || portal_team_id == nil
            UI.user_error! "No Developer Portal team for scheme <#{scheme}>"
        end
        UI.message "Resolved scheme info - flavor: #{flavor}, bundle: #{bundle}, portal_team_id: #{portal_team_id}, platform: #{platform}"

        # get the AppStore Connect team id from the Developer Portal team id
        team_name = teams_map[portal_team_id]
        if team_name == nil
            UI.user_error! "No App Store Connect team found for Developer Portal team <#{portal_team_id}>"
        end
        UI.message "Available teams: #{teams_map}"

        # sync the main app provisioning profile
        match(type: "appstore", git_branch: portal_team_id, clone_branch_directly: true, app_identifier: bundle, platform: platform, readonly: true)
        
        # sync the NotificationService extension provisioning profile when building for the ios platform
        if platform == "ios"
            match(type: "appstore", git_branch: portal_team_id, clone_branch_directly: true, app_identifier: "#{bundle}.notificationservice", platform: platform, readonly: true)
        end
        # sync the TVTopShelf extension provisioning profile when building for the tvos platform
        if platform == "tvos"
            match(type: "appstore", git_branch: portal_team_id, clone_branch_directly: true, app_identifier: "#{bundle}.tvtopshelf", platform: platform, readonly: true)
        end
    
        # build the scheme
        ipa = build(scheme, flavor, build_number, platform)

        # upload the binary to the AppStore
        to_testflight(ipa, team_name)
    end

    lane :deploy_all do |options|
        deploy_configs(configs: all_configs, scheme: options[:scheme])
        UI.message "Finished deploying all configs!"
    end
    
    lane :deploy_custom do |options|
        deploy_configs(configs: custom_configs, scheme: options[:scheme])
        UI.message "Finished deploying custom configs!"
    end
    
    lane :deploy_configs do |options|
        configs = options[:configs] || []
        scheme = options[:scheme]
        configs.select { |config| !scheme || scheme == config[:scheme] }.each { |config|
            config[:flavors].each { |flavor|
                deploy_app(scheme: config[:scheme], flavor: flavor)
            }
        }
    end
    
    lane :match_update do |options|
        type = options[:type] || "appstore"

        # Get the team config
        team_alias = options[:team]
        if team_alias == nil
            require "spaceship"
            clientPortal = Spaceship::Portal.login()
            team_id = Spaceship::Portal.select_team
            team_config = teams_config[team_id]
        else
            filter = teams_config.filter { |team_id, config| config["alias"] == team_alias }
            team_id = filter.keys.first
            team_config = filter.values.first
        end
        if team_id == nil || team_config == nil
            UI.user_error! "No Apple developer team for alias <#{team_alias}>"
        end

        team_alias = team_config["alias"]
        UI.message "Match update for team #{team_alias} (##{team_id})"
        
        # iOS apps
        app_ids_ios = team_config["ios_apps"]
        if app_ids_ios && app_ids_ios.count() > 0
            # for each iOS app id, add its Notification Service counterpart
            ids = app_ids_ios + app_ids_ios.map { |id| "#{id}.notificationservice" }
            UI.message "Update iOS provisioning profiles for #{ids}"
            match(type: type, git_branch: team_id, team_id: team_id, app_identifier: ids, platform: "ios", clone_branch_directly: true, verbose: match_verbose)
        end
        
        # tvOS apps
        app_ids_tvos = team_config["tvos_apps"]
        if app_ids_tvos && app_ids_tvos.count() > 0
            # for each tvOS app id, add its TV Top Shelf counterpart
            ids = app_ids_tvos + app_ids_tvos.map { |id| "#{id}.tvtopshelf" }
            UI.message "Update tvOS provisioning profiles for #{ids}"
            match(type: type, git_branch: team_id, team_id: team_id, app_identifier: ids, platform: "tvos", clone_branch_directly: true, verbose: match_verbose)
        end
    end

    lane :match_update_all do |options|
        teams_config.each do |team_id, config|
            team_alias = config["alias"]
            UI.message "Match update for team #{team_alias} (##{team_id})"
            match_update(team: team_alias)
        end
    end
    
    lane :upload_ipa do |options|
        filename = options[:ipa]
        portal_team_id = options[:team_id]
        team_name = teams_map[portal_team_id]
        if team_name == nil
            UI.user_error! "No App Store Connect team found for Developer Portal team <#{portal_team_id}>"
        end
        to_testflight(filename, team_name)
    end
    
    lane :get_apps_names_and_versions do |options|
        require "spaceship"
        clientPortal = Spaceship::Portal.login()
        teamId = Spaceship::Portal.select_team
        UI.message "Team: #{teamId}"
        
        clientTunes = Spaceship::Tunes.login()
        #Spaceship::Tunes.select_team
        UI.message "Apps: #{clientTunes.teams}"
        all_apps = ""
        clientTunes.teams.each do |team|
            ENV['FASTLANE_ITC_TEAM_ID'] = "#{team['providerId']}"
            Spaceship::Tunes.select_team
            Spaceship::Tunes::Application.all.collect do |app|
                begin
                    live_version = app.get_live_app_store_version.version_string
                    all_apps << "#{app.name} #{live_version} #{app.bundle_id}\n"
                    UI.message "#{app.name} #{live_version} #{app.bundle_id}\n"
                rescue
                    all_apps << "#{app.name} NO Live Version \n"
                    UI.message "#{app.name} NO Live Version \n"
                end
            end
        end
        File.write('all_apps', all_apps[0..-3])
    end
    
    lane :match_import_example do |options|
        # Example of import command:
        # match import --type appstore --skip_provisioning_profiles true --clone_branch_directly true --git_branch XXXXXXXXXX --team_id XXXXXXXXXX --app_identifier XXXXXXXXXX --platform ios
    end

    lane :match_nuke_example do |options|
        # Example of nuke command:
        # bundle exec fastlane run match_nuke type:appstore skip_provisioning_profiles:true clone_branch_directly:true git_branch:XXXXXXXXXX team_id:XXXXXXXXXX safe_remove_certs:true
    end  
end

`./Appfile`
# app_identifier("[[APP_IDENTIFIER]]") # The bundle identifier of your app

apple_id "XXXXXXXXXX" # Your Apple email address

ENV['FASTLANE_USER'] = "XXXXXXXXXX"
ENV['FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD'] = "XXXXXXXXXX"

# For more information about the Appfile, see:
#     https://docs.fastlane.tools/advanced/#appfile

fastlane gems

Gem Version Update-Status
fastlane 2.220.0 ✅ Up-To-Date

Loaded fastlane plugins:

No plugins Loaded

Loaded gems
Gem Version
error_highlight 0.5.1
did_you_mean 1.6.3
syntax_suggest 1.0.2
bundler 2.4.8
pathname 0.2.1
rake 13.2.0
base64 0.2.0
nkf 0.2.0
rexml 3.2.6
CFPropertyList 3.0.7
public_suffix 5.0.5
addressable 2.8.6
artifactory 3.0.17
atomos 0.1.3
aws-eventstream 1.3.0
aws-partitions 1.907.0
aws-sigv4 1.8.0
jmespath 1.6.2
aws-sdk-core 3.191.6
aws-sdk-kms 1.78.0
aws-sdk-s3 1.146.1
babosa 1.0.4
claide 1.1.0
colored 1.2
colored2 3.1.2
highline 2.0.3
commander 4.6.0
declarative 0.0.20
digest-crc 0.6.5
domain_name 0.6.20240107
dotenv 2.8.1
emoji_regex 3.2.3
excon 0.110.0
faraday-em_http 1.0.0
faraday-em_synchrony 1.0.0
faraday-excon 1.1.0
faraday-httpclient 1.0.1
multipart-post 2.4.0
faraday-multipart 1.0.4
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
ruby2_keywords 0.0.5
faraday 1.10.3
http-cookie 1.0.5
faraday-cookie_jar 0.0.7
faraday_middleware 1.2.0
fastimage 2.3.1
gh_inspector 1.1.3
jwt 2.8.1
multi_json 1.15.0
os 1.1.4
signet 0.19.0
googleauth 1.8.1
httpclient 2.8.3
mini_mime 1.1.5
trailblazer-option 0.1.2
uber 0.1.0
representable 3.2.0
retriable 3.1.2
google-apis-core 0.11.3
google-apis-androidpublisher_v3 0.54.0
google-apis-playcustomapp_v1 0.13.0
google-cloud-env 1.6.0
google-apis-iamcredentials_v1 0.17.0
google-apis-storage_v1 0.31.0
google-cloud-errors 1.4.0
google-cloud-core 1.7.0
google-cloud-storage 1.47.0
json 2.7.2
mini_magick 4.12.0
naturally 2.2.1
optparse 0.4.0
plist 3.7.1
rubyzip 2.3.2
security 0.1.5
simctl 1.6.10
terminal-notifier 2.0.0
unicode-display_width 2.5.0
terminal-table 3.0.2
tty-screen 0.8.2
tty-cursor 0.7.1
tty-spinner 0.9.3
word_wrap 1.0.0
nanaimo 0.3.0
xcodeproj 1.24.0
rouge 2.0.7
xcpretty 0.3.0
xcpretty-travis-formatter 1.0.1

generated on: 2024-06-05

aureliencolas avatar Jun 05 '24 08:06 aureliencolas