MacOS 项目的 Fastlane + GitHub Actions 错误

问题描述 投票:0回答:1

我尝试使用 Fastlane 设置 GitHub Actions 并收到以下错误:

no implicit conversion of nil into String
。以下是完整输出:

default_platform(:mac)

DEVELOPER_APP_ID = ENV["DEVELOPER_APP_ID"]
DEVELOPER_APP_IDENTIFIER = ENV["DEVELOPER_APP_IDENTIFIER"]
PROVISIONING_PROFILE_SPECIFIER = ENV["PROVISIONING_PROFILE_SPECIFIER"]
TEMP_KEYCHAIN_USER = ENV["TEMP_KEYCHAIN_USER"]
TEMP_KEYCHAIN_PASSWORD = ENV["TEMP_KEYCHAIN_PASSWORD"]
APPLE_ISSUER_ID = ENV["APPLE_ISSUER_ID"]
APPLE_KEY_ID = ENV["APPLE_KEY_ID"]
APPLE_KEY_CONTENT = ENV["APPLE_KEY_CONTENT"]
GIT_AUTHORIZATION = ENV["GIT_AUTHORIZATION"]

def delete_temp_keychain(name)
  UI.message("Debug: Deleting temporary keychain #{name}...")
  delete_keychain(
    name: name
  ) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
end

def create_temp_keychain(name, password)
  UI.message("Debug: Creating temporary keychain #{name}...")
  create_keychain(
    name: name,
    password: password,
    unlock: false,
    timeout: 0
  )
end

def ensure_temp_keychain(name, password)
  delete_temp_keychain(name)
  if password.nil? || password.empty?
    UI.error("Error: Password for temporary keychain is missing.")
  end
  create_temp_keychain(name, password)
end

platform :mac do
  lane :beta do
    UI.message("Debug: Starting the beta lane...")
    
    keychain_name = TEMP_KEYCHAIN_USER
    keychain_password = TEMP_KEYCHAIN_PASSWORD

    UI.message("Debug: Ensuring temporary keychain...")
    ensure_temp_keychain(keychain_name, keychain_password)

    UI.message("Debug: Validating keychain variables...")
    if keychain_password.nil? || keychain_password.empty?
      UI.error("Error: TEMP_KEYCHAIN_PASSWORD is not set.")
    end

    UI.message("Debug: Creating App Store Connect API key...")
    api_key = app_store_connect_api_key(
      key_id: APPLE_KEY_ID,
      issuer_id: APPLE_ISSUER_ID,
      key_content: APPLE_KEY_CONTENT,
      duration: 1200,
      in_house: false
    )
    
    UI.message("Debug: Incrementing build number...")
    increment_build_number(xcodeproj: "Meter.xcodeproj")
    
    UI.message("Debug: Running match...")
    match(
      type: 'appstore',
      app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
      git_basic_authorization: Base64.strict_encode64(GIT_AUTHORIZATION),
      readonly: true,
      keychain_name: keychain_name,
      keychain_password: keychain_password,
      api_key: api_key
    )

    UI.message("Debug: Building the project with gym...")
    gym(
      configuration: "Release",
      project: "Meter.xcodeproj",
      scheme: "Meter",
      export_method: "app-store",
      export_options: {
        provisioningProfiles: {
          DEVELOPER_APP_ID => PROVISIONING_PROFILE_SPECIFIER
        }
      }
    )

    UI.message("Debug: Uploading to TestFlight with pilot...")
    pilot(
      apple_id: "#{DEVELOPER_APP_ID}",
      app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
      skip_waiting_for_build_processing: true,
      skip_submission: true,
      distribute_external: false,
      notify_external_testers: false,
      ipa: "./your_app_name.ipa"
    )

    UI.message("Debug: Deleting temporary keychain...")
    delete_temp_keychain(keychain_name)

    UI.message("Debug: Beta lane completed successfully!")
  end
end

这是我正在使用的Fastfile的内容:

# Fastfile
default_platform(:mac)

DEVELOPER_APP_ID = ENV["DEVELOPER_APP_ID"]
DEVELOPER_APP_IDENTIFIER = ENV["DEVELOPER_APP_IDENTIFIER"]
PROVISIONING_PROFILE_SPECIFIER = ENV["PROVISIONING_PROFILE_SPECIFIER"]
TEMP_KEYCHAIN_USER = ENV["TEMP_KEYCHAIN_USER"]
TEMP_KEYCHAIN_PASSWORD = ENV["TEMP_KEYCHAIN_PASSWORD"]
APPLE_ISSUER_ID = ENV["APPLE_ISSUER_ID"]
APPLE_KEY_ID = ENV["APPLE_KEY_ID"]
APPLE_KEY_CONTENT = ENV["APPLE_KEY_CONTENT"]
GIT_AUTHORIZATION = ENV["GIT_AUTHORIZATION"]

def delete_temp_keychain(name)
  UI.message("Debug: Deleting temporary keychain #{name}...")
  delete_keychain(
    name: name
  ) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
end

def create_temp_keychain(name, password)
  UI.message("Debug: Creating temporary keychain #{name}...")
  create_keychain(
    name: name,
    password: password,
    unlock: false,
    timeout: 0
  )
end

def ensure_temp_keychain(name, password)
  delete_temp_keychain(name)
  if password.nil? || password.empty?
    UI.error("Error: Password for temporary keychain is missing.")
  end
  create_temp_keychain(name, password)
end

platform :mac do
  lane :beta do
    UI.message("Debug: Starting the beta lane...")
    
    keychain_name = TEMP_KEYCHAIN_USER
    keychain_password = TEMP_KEYCHAIN_PASSWORD

    UI.message("Debug: Ensuring temporary keychain...")
    ensure_temp_keychain(keychain_name, keychain_password)

    UI.message("Debug: Validating keychain variables...")
    if keychain_password.nil? || keychain_password.empty?
      UI.error("Error: TEMP_KEYCHAIN_PASSWORD is not set.")
    end

    UI.message("Debug: Creating App Store Connect API key...")
    api_key = app_store_connect_api_key(
      key_id: APPLE_KEY_ID,
      issuer_id: APPLE_ISSUER_ID,
      key_content: APPLE_KEY_CONTENT,
      duration: 1200,
      in_house: false
    )
    
    UI.message("Debug: Incrementing build number...")
    increment_build_number(xcodeproj: "Meter.xcodeproj")
    
    UI.message("Debug: Running match...")
    match(
      type: 'appstore',
      app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
      git_basic_authorization: Base64.strict_encode64(GIT_AUTHORIZATION),
      readonly: true,
      keychain_name: keychain_name,
      keychain_password: keychain_password,
      api_key: api_key
    )

    UI.message("Debug: Building the project with gym...")
    gym(
      configuration: "Release",
      project: "Meter.xcodeproj",
      scheme: "Meter",
      export_method: "app-store",
      export_options: {
        provisioningProfiles: {
          DEVELOPER_APP_ID => PROVISIONING_PROFILE_SPECIFIER
        }
      }
    )

    UI.message("Debug: Uploading to TestFlight with pilot...")
    pilot(
      apple_id: "#{DEVELOPER_APP_ID}",
      app_identifier: "#{DEVELOPER_APP_IDENTIFIER}",
      skip_waiting_for_build_processing: true,
      skip_submission: true,
      distribute_external: false,
      notify_external_testers: false,
      ipa: "./your_app_name.ipa"
    )

    UI.message("Debug: Deleting temporary keychain...")
    delete_temp_keychain(keychain_name)

    UI.message("Debug: Beta lane completed successfully!")
  end
end

不太确定到底是什么导致了 nil 错误;任何帮助表示赞赏!

xcode macos github-actions fastlane
1个回答
0
投票

您遇到的错误消息“没有将 nil 隐式转换为 String”通常发生在您尝试对 nil 变量执行字符串操作时。在 Fastlane 脚本中,有几个地方使用的环境变量可能为零或为空。让我们检查一下您的脚本并找出潜在的问题:

检查

TEMP_KEYCHAIN_USER
TEMP_KEYCHAIN_PASSWORD

确保设置了

TEMP_KEYCHAIN_USER
TEMP_KEYCHAIN_PASSWORD
环境变量且不为零。 确保您已在 GitHub Actions 工作流程中或触发此 Fastlane 脚本的任何位置定义了这些环境变量。 检查
APPLE_KEY_ID
APPLE_ISSUER_ID
APPLE_KEY_CONTENT

这些环境变量也应该被定义并且不为零。 验证您为这些环境变量设置的值是否正确。 检查

DEVELOPER_APP_ID
DEVELOPER_APP_IDENTIFIER
PROVISIONING_PROFILE_SPECIFIER

确保这些环境变量已设置且不为零。 确认这些值正确并符合您的项目设置。 验证

GIT_AUTHORIZATION

确保

GIT_AUTHORIZATION
已定义且不为零。 确保它包含格式正确的必要凭据。 在试点步骤中检查 ipa:“./your_app_name.ipa”:

确保项目根目录中有一个名为“your_app_name.ipa”的 IPA 文件。如果文件位于不同的目录中,则需要指定正确的路径。 此外,请确保在 GitHub Actions 密钥或环境变量设置中正确定义所有环境变量。仔细检查变量名称中的拼写错误或差异。

通过解决这些问题并确保正确设置所有必需的环境变量,您应该能够使用 Fastlane 解决 GitHub Actions 工作流程中的“没有将 nil 隐式转换为字符串”错误。

此外,当您需要验证它不是 nil 或空时,您可以使用

to_s
来简化代码,因为如果变量在转换为字符串时为 nil,则直接是空引号
''

UI.message("Debug: Validating keychain variables...")

# e.g
if keychain_password.to_s.empty?
# if keychain_password.nil? || keychain_password.empty?
  UI.error("Error: TEMP_KEYCHAIN_PASSWORD is not set.")
end
© www.soinside.com 2019 - 2024. All rights reserved.