我们的 AI 引擎 Neutron 在加州大学伯克利分校的 CyberGym 基准测试中取得了 96.75% 的成绩。 了解更多

产品

产品

使用 Jenkins、GitHub Actions 和 Azure DevOps 实现移动应用 CI/CD

本文介绍为移动应用实施 CI/CD 流水线时面临的主要挑战,并举例说明如何在最常用的移动 CI/CD 工具中为 Android 和 iOS 应用实现 CI/CD 流水线。

在将安全扫描集成到 CI/CD 流水线中的团队里,85% 能够遵守其补丁 SLO,修复漏洞更快,修改代码更频繁,并且对自己的代码库有更好的理解。

本文将介绍为移动应用实施 CI/CD 流水线时面临的主要挑战。我们还将举例说明如何在最常用的移动 CI/CD 工具中为 Android 和 iOS 应用实现持续集成流水线。

在将安全检查纳入 CI/CD 流水线之前,我们必须确保这些流水线构建正确、运行稳定,并且具备合适的可观测性,以便在出现故障时进行修复。

以下是我们在移动应用中采用 CI/CD 时常见的一些挑战:

  • 缺乏 CI/CD 专业知识:

    大多数 DevOps 解决方案都需要深厚的 CI/CD 专业知识,才能正确地搭建、定制和维护自动化工作流与流程。大多数应用开发人员需要时间和经验来掌握这套技能。
  • 职责归属不清:

    实施 CI/CD 并不是一次性的任务。与所有由人编写的代码一样,它可能会失败、出错或出现意外行为。因此,CI/CD 流水线的管理或实现不善,往往使得立即找出故障原因成为一项繁琐的工作。这又进一步增加了将问题转交给相关团队修复代码错误的难度。

  • 局限于 Dev 和 QA 环境而忽视 Prod 环境:

    移动应用通常由安装在设备上的客户端二进制文件和通过 API 与之通信的后端组成。 CI/CD 流水线可能使用不同的配置和环境来运行测试。一个常见的错误是使用 Dev 和 QA 环境进行测试,而忽略了它们与 Prod 环境之间的差异。 这样一来,生产环境中的代码就未经测试,可能存在错误、安全问题或意外错误。

  • 忽视动态分析:

    许多公司实施的 CI 流水线只包含静态分析。这主要是因为自动化应用的动态分析存在困难。 静态分析旨在分析二进制文件或源代码,以找出已知的漏洞模式。然而,众所周知,静态分析会针对轻微的软件缺陷和未被利用的缺陷产生过多告警。 这就是 OWASP 标准建议同时实施静态分析和动态分析的原因。动态分析旨在应用运行时检测安全漏洞。它只覆盖应用中实际使用的范围,并对所发现的问题提供很高的置信度。

  • 难以运行 UI 自动化:

    在 CI/CD 流水线中,自动化 UI 交互是提高测试覆盖率、确保测试可扩展性和质量的重要一步。常见的挑战在于将所有 UI 交互自动化,并确保它们在不同的应用版本、操作系统版本和多种设备上都保持稳定。

  • CI/CD 供应商的隐性限制:

    要为移动应用建立完全自动化的 CI/CD 流水线,您需要满足移动应用严格的操作系统要求、严谨的代码签名、频繁更新的 SDK 和工具、设备测试以及应用商店提交等要求。 因此,选择合适的 CI/CD 供应商对于满足您的需求、简化实施和维护至关重要。

现在,我们来看看如何将移动应用(Android 和 iOS)的构建添加到一些最常用的 CI/CD 平台中。

使用 Jenkins 实现 Android 应用的持续集成

我们将学习如何在 Jenkins 中从源代码生成 Android APK。这里假设您已经安装了 Jenkins。

  • 第 1 步:安装 Java JDK:
    在终端中运行:
sudo apt install default-jdk
  • 第 2 步:安装 Android SDK:
    访问 Android 下载页面,获取表格中 Command line tools only > Linux 对应的链接。不要下载任何内容,只需复制该链接。
# here you paste the link you grabbed in the developer.android.com site
sudo -iu jenkins wget https://dl.google.com/android/repository/commandlinetools-linux-8512546_latest.zip
sudo -iu jenkins mkdir android-sdk
sudo -iu jenkins unzip commandlinetools-linux-8512546_latest.zip -d android-sdk

# this step is important to accept the Android SDK license
yes |sudo -iu jenkins android-sdk/tools/bin/sdkmanager --licenses
  • 第 3 步:安装 Gradle 插件:

管理 Jenkins
管理 Jenkins

.1 打开 Jenkins:Manage Jenkins >> Manage Plugins >> Available

.2 搜索 Gradle

搜索 Gradle
搜索 Gradle

.3 点击 Install

Gradle 已安装
Gradle 已安装

  • 第 4 步:配置 Jenkins:

.1 打开 Jenkins:Manage Jenkins >> Configure System >> Global properties >> Environment variables

添加变量
添加变量

.2 添加以下变量:

  # depending on your local paths
  ANDROID_HOME : /var/lib/jenkins/android-sdk
  JAVA_HOME : /usr/lib/jvm/java-11-openjdk-amd64

添加 Android Home 变量
添加 Android Home 变量

  • 第 5 步:创建 Android 构建任务:

.1 打开 Jenkins:New Item

.2 输入任务名称

.3 选择 Freestyle project 并点击 OK

.4 进入 Source Code Management,勾选 Git 并填写:

  • Repository URL:您的代码仓库的 Git URL。该 URL 可从 GitHub 获取,格式应为 git@github.com:{username}/{repo}.git

  • Credentials:选择您的凭据,或在凭据菜单中新建一个。

  • Branches to build:branch_name

.5 在 Build 部分,选择 Invoke Gradle script

Gradle 配置
Gradle 配置

.8 填写您的任务名称

.9 在 Post-build Actions 中填写 Archive artifacts:**/*.apk

.10 点击 Save

  • 第 6 步:启动构建:

    在任务仪表板中点击 Build Now,即可看到任务开始运行。 构建成功后,您可以在项目信息中看到生成的 Android 应用。

APK 构建产物
APK 构建产物

使用 Jenkins 实现 iOS 应用的持续集成

  • 第 1 步:安装 Jenkins 及 XCode 插件(需要 MacOS):

.1 打开 Jenkins:Manage Jenkins >> Manage Plugins >> Available

.2 搜索 Xcode integration

Xcode Jenkins 集成
Xcode Jenkins 集成

.3 点击 Install

  • 第 2 步:在 Jenkins 全局配置中创建开发团队:

.1 打开 Jenkins:Manage Jenkins >> Configure System

.2 进入 Xcode builder 部分

.3 进入 Apple Development Teams 部分并点击 Add 按钮

.4 填写 Team Name 和 Development Team ID 两个字段

Xcode Jenkins 开发团队
Xcode Jenkins 开发团队

.5 添加一个 Keychain 部分

.6 填写 Keychain Name 和 Keychain password 的值(Keychain path 会自动填好)

Xcode Jenkins 钥匙串
Xcode Jenkins 钥匙串

.7 点击 Apply 并 Save

  • 第 3 步:配置 Jenkins 任务以克隆代码仓库:

.1 进入 Jenkins 工作区中的项目路径(/Users/Shared/Jenkins/Home/workspace)

.2 使用 Xcode 打开项目

.3 在 Xcode 的 General 选项卡中,检查 Provisioning profile 及所有信息是否正确

.4 您可以尝试使用 Xcode 构建项目,以确保所有信息正确无误

.5 不应勾选 Automatically manage signing 复选框

.6 记下 Team Name 和 Bundle Identifier,因为我们将在 Jenkins 配置中用到它们

  • 第 5 步:在 Jenkins 中配置构建:

.1 打开 Jenkins,进入您的项目,然后点击 configure

.2 在 Build 部分,点击 build 步骤按钮并选择 Xcode 选项。这会添加与 Xcode 相关的字段。

.3 在 General build settings 中,点击 Settings 按钮

.4 选择您最近添加到 Jenkins 全局配置中的 Development Team

.5 填写 Xcode Schema File:

.6 选择 Pack application, build and sign .ipa? 选项。

在 Jenkins 中打包并签名 IPA
在 Jenkins 中打包并签名 IPA

.7 用于从 .app 生成 .ipa 文件的导出方式。其值应为“development”“ad-hoc”“enterprise”或“app-store”之一。

.8 .ipa filename pattern:IPA 文件名的模式。您可以在该字符串中使用 ${VERSION} 和 ${BUILD_DATE}(yyyy.MM.dd)。

.9 进入 Code signing & OS X keychain 选项

.10 选择 Manual signing

.11 填写 Bundle ID 和 Provisioning profile UUID(可在您的 provisioning profile .mobileprovision 文件中找到)

.12 选择 Unlock Keychain

.13 从下拉菜单中选择最近创建的 Keychain 值

.14 进入 Advanced Xcode build 选项部分

.15 填写 Xcode Workspace File 字段:,以及 Xcode Project Directory:$WORKSPACE

.16 点击 Apply 并 Save

  • 第 6 步:启动构建:

在任务仪表板中点击 Build Now,即可看到任务开始运行。

构建成功后,您可以在项目信息中看到生成的 IPA 应用。

使用 GitHub Actions 实现 Android 应用的持续集成

GitHub Actions 提供的运行器(runner)允许您在 Linux、Mac 和 Windows 上运行构建。

所有运行器都已预先安装并配置好 Java 和 Android(预装软件的列表相当长)。 无需额外设置,这些运行器即可直接构建大多数 Android 项目。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout the code
        uses: actions/checkout@v2
      - name: Build the app
        run: ./gradlew build

使用 GitHub Actions 实现 iOS 应用的持续集成

对于 IPA 构建,我们将使用 yukiarrr/ios-build-action 任务。该 Action 会构建 iOS 项目,并可导出为 IPA 文件。 您可以在 GitHub 代码仓库中查看完整文档

name: Build and sign Ipa file

on:
 push:
   branches: [ main ]
 pull_request:
   branches: [ main ]

jobs:
 build:
   runs-on: macos-latest

   steps:
   - uses: actions/checkout@v2
   - name: Build and export iOS
     uses: yukiarrr/ios-build-action@v1.5.0
     with:
       project-path:
       workspace-path: ".xcworkspace path"
       scheme: "project name"
       export-method: "Choose app-store, ad-hoc, package, enterprise, development"
       configuration: "Choose Debug or Release"
       output-path: artifacts/output.ipa
       p12-base64: ${{ secrets.P12_BASE64 }}
       certificate-password: ${{ secrets.P12_PASSWORD }}
       mobileprovision-base64: ${{ secrets.ADHOC_MOBILEPROVISION_BASE64 }}
       code-signing-identity: ${{ secrets.CODE_SIGNING_IDENTITY }}
       team-id: ${{ secrets.TEAM_ID }}

使用 Azure DevOps 实现 Android 应用的持续集成

  • 第 1 步:准备流水线:

Azure DevOps
Azure DevOps

.1 打开您的项目,在左侧面板中进入 Pipelines 部分

.2 点击 Create Pipeline

.3 选择您的 Git 代码仓库

此时会生成一个空的 Yaml 流水线。接下来我们需要使用 Gradle 构建二进制文件。

  • 第 2 步:使用 Gradle 任务构建 APK 文件:

.1 点击 show assistant

Azure DevOps 显示助手
Azure DevOps 显示助手

.2 搜索 Gradle

Azure DevOps Gradle
Azure DevOps Gradle

.3 您可以关闭 JUnit Test Results 部分下的 Publish to Azure Pipeline

.4 设置用于构建文件的任务名称

.5 点击 Add 按钮

.6 点击 Save 保存我们的 CI 流水线

如果您希望对生成的文件运行其他任务,还可以添加“Copy files”和“Publish build artifacts”任务,将生成的文件注入流水线。

使用 Azure DevOps 实现 iOS 应用的持续集成

  • 第 1 步:准备流水线:

.1 打开您的项目,在左侧面板中进入 Pipelines 部分

.2 点击 Create Pipeline

.3 选择您的 Git 代码仓库

此时会生成一个空的 Yaml 流水线。接下来我们需要使用 Gradle 构建二进制文件。

  • 第 2 步:使用 Gradle 任务构建 APK 文件:

我们需要 provisioning profile 和 iOS 证书来为 IPA 文件签名。

为了将它们上传到流水线,我们将使用 Secure files 部分:

.1 进入 pipelines -> Library -> Secure files

Azure DevOps 安全文件
Azure DevOps 安全文件

.2 上传您的 provisioning 文件。在本例中,我将其命名为 my_provision_profile_ostorlab

.3 导出 certificate public key(.p12)并上传。我将其命名为 my_certificate.p12

.4 返回您的流水线并添加三个变量:

p12FileName = my_certificate.p12
p12Password = my_certificate_password
provisioningProfile = my_provision_profile_ostorlab

Azure DevOps 变量
Azure DevOps 变量

.5 点击 show assistant

.6 搜索 install apple provisioning

Azure DevOps Gradle
Azure DevOps Gradle

.7 在 provProfileSecureFile 中填写变量 $(provisioningProfile)

.8 点击 Add

.9 点击 show assistant

.10 搜索 install apple certificate

Azure DevOps Gradle
Azure DevOps Gradle

.11 使用变量内容填写文件名和密码

.12 点击 Add

  • 第 3 步:构建 IPA 文件并签名:

要构建 .ipa 文件,我们需要使用 macOS 作为 vmImage。

.1 我们需要将 build configuration 添加为变量。您可以将其值设为 Debug 或 Release。

.2 我们需要添加 SDK 变量。在 macOS 的 Terminal 应用中运行 xcodebuild -showsdks,即可显示有效的 SDK 列表。

.3 点击 show assistant

.4 搜索 Xcode

Azure DevOps Xcode
Azure DevOps Xcode

.5 在 Signing style 中,选择 Manual signing

.6 在 Signing identity 中填写值 $(APPLE_CERTIFICATE_SIGNING_IDENTITY)。该变量对应我们之前添加的“Install Apple Certificate”

.7 在 Provisioning profile UUID 中填写由“Install Apple Provisioning Profile”任务定义的值 $(APPLE_PROV_PROFILE_UUID)。

.8 点击 Add

.9 点击 save 保存我们的 CI 流水线。

首次运行构建时会失败,并要求您授予对变量和安全文件的访问权限。点击 Authorize resources,然后重新运行构建。

在本文中,我们介绍了实施 CI/CD 流水线时会遇到的一些挑战,还讨论了如何在最常用的 CI 平台中构建 APK 和 IPA 移动应用。 CI 的实施应辅以 CD 流水线,以便在评审流程结束后自动完成部署。 由于移动应用领域有多种用于开发和构建应用的框架,CI 的实施方式会因框架工具而异。

下一篇文章将介绍 flutter 框架,以及如何在这些 CI/CD 平台中自动化构建。