为 React-native ios 应用程序构建 ci/cd 管道:如何在 gitlab-ci 中运行 expo build?

dan*_*789 2 continuous-integration ios gitlab-ci react-native

我正在帮助为使用expo开发的 React-Native 应用程序建立 gitlab ci 管道。这是我的gitlab-ci.yml

\n\n
image: node/apline\ncache:\n  key: ${CI_COMMIT_REF_SLUG}\n  paths:\n    - ~/.npm\n\nstages:\n  - deploy\n  - tag\nbefore_script:\n  - echo $CI_BUILD_REF\n  - echo $CI_PROJECT_DIR\n  - apk add --no-cache bash build-base gcc git python3 curl\n  - PATCH=`git log --pretty=oneline | wc -l | sed -e \'s/^[[:space:]]*//\'`\n  - VERSION=`cat VERSION`\n  - VERSION=${VERSION%?}\n  - TAG="${VERSION}${PATCH}"\n  - echo "Build version = ${TAG}"\n\nexpo-build:\n  stage: deploy\n  artifacts:\n    paths:\n    - ipas/\n  script:\n    - sed -i "s/0.0.0/${TAG}/g" app.json\n    - npm ci --production --cache .npm --prefer-offline\n    - npx expo login -u $EXPO_USERNAME -p $EXPO_PASSWORD\n    - EXPO_DEBUG=true npx expo build:ios --non-interactive\n    - mkdir -p ipas\n    - curl "$(npx expo url:ipa --non-interactive)" -o ipas/my-app-$TAG.ipa\n  only:\n    - master\n
Run Code Online (Sandbox Code Playgroud)\n\n

我想做的是让应用程序在.ipa每次推动掌握时构建一个新的应用程序。这样我就可以将其上传.ipa到我的 mdm 来分发应用程序。

\n\n

问题是,如果我每个构建一个不同的应用程序(我有多个应用程序尝试执行此操作),则似乎构建步骤需要在本地运行,然后才能再次在 ci 中运行。我的意思是,npx expo build:ios --non-interactive每次我使用我的苹果凭据进行单独的构建时,该命令都需要干预来选择正确的证书。

\n\n

以下是失败构建的输出(之前在管道中已成功,无需更改代码):

\n\n
- Making sure project is set up correctly...\n[17:26:33] Checking if there is a build in progress...\n[17:26:34] Fetching available credentials\n[17:26:38] Unable to validate distribution certificate due to insufficient Apple Credentials\n[17:26:38] Unable to determine validity of Push Keys due to insufficient Apple Credentials\n[17:26:38] CommandError: Input is required, but Expo CLI is in non-interactive mode.\nRequired input:\n> Push Notifications Key (Key ID: XXX, Team ID: XXX)\n>     not used by any apps\n>     \xe2\x9c\x85 Currently valid on Apple\'s servers. \n>  Would you like to use this Push Key?\n   at prompt (/expo-cli@3.17.17/src/prompt.ts:22:11)\n   at CreateOrReusePushKey.open (/expo-cli@3.17.17/src/credentials/views/IosPushCredentials.ts:281:31)\n   at processTicksAndRejections (internal/process/task_queues.js:97:5)\n   at CredentialsManager.run (/expo-cli@3.17.17/src/credentials/route.ts:42:12)\n   at runCredentialsManager (/expo-cli@3.17.17/src/credentials/route.ts:13:10)\n   at IOSBuilder.produceCredentials (/expo-cli@3.17.17/src/commands/build/ios/IOSBuilder.ts:168:7)\n   at IOSBuilder.prepareCredentials (/expo-cli@3.17.17/src/commands/build/ios/IOSBuilder.ts:124:7)\n   at IOSBuilder.run (/expo-cli@3.17.17/src/commands/build/ios/IOSBuilder.ts:46:7)\n   at IOSBuilder.command (/expo-cli@3.17.17/src/commands/build/BaseBuilder.ts:29:7)\n   at Command.<anonymous> (/expo-cli@3.17.17/src/exp.ts:85:7) {\n code: \'NON_INTERACTIVE\',\n isCommandError: true\n}\n[17:26:39] Failed to prepare all credentials. \nThe next time you build, we will automatically use the following configuration:\n[17:26:39]\n[17:26:39] Project Credential Configuration:\n[17:26:39]   Experience: @team/app, bundle identifier: com.app.profile\n[17:26:39]     Provisioning profile (ID: XXX)\n[17:26:39]     Apple Team ID: XXX,  Apple Team Name: ---------\n[17:26:39]\n[17:26:39]   Distribution Certificate - Certificate ID: XXX\n[17:26:39]     Apple Team ID: XXX,  Apple Team Name: A Company, LLC (In-House)\n[17:26:39]     used by\n     @team/app, (com.app.profile)\n[17:26:39] \n[17:26:39] Error\n   at CredentialsManager.doQuit [as _quit] (/expo-cli@3.17.17/src/credentials/views/Select.ts:176:9)\n   at CredentialsManager.run (/expo-cli@3.17.17/src/credentials/route.ts:49:42)\n   at runCredentialsManager (/expo-cli@3.17.17/src/credentials/route.ts:13:10)\n   at IOSBuilder.produceCredentials (/expo-cli@3.17.17/src/commands/build/ios/IOSBuilder.ts:168:7)\n   at IOSBuilder.prepareCredentials (/expo-cli@3.17.17/src/commands/build/ios/IOSBuilder.ts:124:7)\n   at IOSBuilder.run (/expo-cli@3.17.17/src/commands/build/ios/IOSBuilder.ts:46:7)\n   at IOSBuilder.command (/expo-cli@3.17.17/src/commands/build/BaseBuilder.ts:29:7)\n   at Command.<anonymous> (/expo-cli@3.17.17/src/exp.ts:85:7)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我的问题是:expo/gitlab-ci 支持这个工作流程吗?如果是,我做错了什么?我希望它能够可靠地构建,这样我就可以为这个反应本机应用程序开发一个可靠的 ci/cd 管道。如果对于这个用例(构建和部署react-native ios应用程序)我有更好的流程可以遵循,我也洗耳恭听。任何事情都有帮助。

\n

dan*_*789 5

阅读文档后,并直接与 expo Slack 上的一些好心人交谈。这是我为了在 gitlab-ci 中为我的 React-native ios 应用程序获得可靠的 ci 构建而最终得出的结论。

这是我的文件中的构建阶段gitlab-ci.yml

expo-build:
  stage: deploy
  artifacts:
    paths:
    - ipas/
  script:
    - sed -i "s/0.0.0/${TAG}/g" app.json
    - npm ci --prefer-offline
    - echo $P8_KEY > ${HOME}/${CI_PROJECT_NAME}.p8
    - echo $P12_DIST | base64 -d > ${HOME}/${CI_PROJECT_NAME}.p12
    - echo $PROVISIONING_PROFILE | base64 -d > ${HOME}/${CI_PROJECT_NAME}.mobileprovision
    - npx expo login -u $EXPO_USERNAME -p $EXPO_PASSWORD
    - npx expo build:ios --team-id $APPLE_TEAM_ID --push-id $PUSH_KEY_ID --dist-p12-path ${HOME}/${CI_PROJECT_NAME}.p12 --push-p8-path ${HOME}/${CI_PROJECT_NAME}.p8 --provisioning-profile-path ${HOME}/${CI_PROJECT_NAME}.mobileprovision --no-publish --non-interactive
    - mkdir -p ipas
    - curl "$(npx expo url:ipa --non-interactive)" -o ipas/${CI_PROJECT_NAME}-${TAG}.ipa
  only:
    - ci-build-test # Build api without pushing to master (protected branch)
    - master
Run Code Online (Sandbox Code Playgroud)

请注意,构建命令包含以下所有标志:

--team-id 
--push-id
--dist-p12-path 
--push-p8-path
--provisioning-profile-path 
--no-publish 
--non-interactive
Run Code Online (Sandbox Code Playgroud)

需要注意的是所有正在使用的环境变量。请注意,我的苹果开发者和博览会帐户用户名和密码都被使用:

  • 苹果ID
    • 我的苹果ID
    • 用于与 Apple 开发者门户交互
    • 需要从命令行登录苹果
  • APPLE_TEAM_ID
    • 来自 Apple 开发者门户的我的团队 ID
    • ci 命令未明确使用但必须env与此键一起使用
  • EXPO_APPLE_PASSWORD
    • 使用我的 appleid 生成的应用程序特定密码
    • 需要从命令行登录苹果
    • ci 命令未明确使用但必须env与此键一起使用
  • EXPO_USERNAME
    • 我的博览会帐户用户名
  • EXPO_PASSWORD
    • 上述用户帐户的密码

以下值是在通过标准构建提示构建应用程序后创建的expo bi,然后使用 获取创建/生成的凭据expo fetch:ios:certs。然后,二进制文件被编码为 base64,然后作为字符串上传。它们也作为环境变量公开。

  • P8_KEY
    • 应用程序名称_apns_key.p8
    • 直接在CI中使用
  • P12_DIST
    • 应用程序名称_dist.p12
    • 在作为环境变量上传之前以 Base64 进行编码
  • 配置_配置文件
    • 应用程序名称.mobileprovision
    • 在作为环境变量上传之前以 Base64 进行编码
  • PUSH_KEY_ID
    • 通过命令输出expo fetch:ios:certs
    • 最初,当我第一次构建应用程序时,我让 expo 生成这个。
  • EXPO_IOS_DIST_P12_PASSWORD
    • 从博览会生成的签名证书
    • 通过命令输出expo fetch:ios:certs

我希望这可以帮助任何和我有同样问题的人!