面向-IOS-开发者的-AWS-和-DevOps-入门指南-全-

面向 IOS 开发者的 AWS 和 DevOps 入门指南(全)

原文:Beginning DevOps on AWS for iOS Development

协议:CC BY-NC-SA 4.0

一、iOS 应用开发基础

本章面向 iOS 应用开发初学者。如果你是 iOS 开发者或者有开发 iOS 应用的经验,可以跳过。

为了开发 iOS 应用,苹果提供了几种工具和资源。iOS 应用可以用原生编程语言开发,如 Swift 或 Objective-C 等跨平台语言。

在本章中,我将介绍 iOS 应用开发的要求和基本构建模块,同时通过使用 Swift 构建一个示例应用并在 iOS 设备和 iOS 模拟器上测试该应用,引导您完成整个过程。

开发要求

作为一名 iOS 开发者,你需要一台 macOS 设备和一个苹果开发者账号才能开始开发。

苹果个人计算机

要开始 iOS 开发,需要一台 Mac。它有笔记本和台式机两种版本。目前的笔记本版本有 MacBook Air 和 MacBook Pro,台式机版本有 iMac、Mac Pro、Mac mini。在图 1-1 中可以看到一些 Mac 型号。

图 1-1

比较各种 Mac 型号

苹果开发者账户

你可以免费注册成为苹果开发者。你只需要一个苹果 ID。有了免费的开发者账户,你就可以在你的 Mac 上安装 Xcode(我们将在下一节介绍)、iOS 开发文档、样本代码、苹果开发者论坛和错误报告。你也可以在设备上测试你的应用。免费的苹果开发者账号足够本地测试和开发。但是,要分发应用,您需要注册苹果开发者计划。

苹果开发者计划是一个付费会员计划,按年计费。如果您对创建应用并在 App Store 上发布感兴趣,这是必需的。关于苹果开发者计划的更多细节可以在苹果网站上找到,如图 1-2 所示。

图 1-2

苹果开发者计划

迅速发生的

Swift 是苹果公司在 2014 年开发的一种编程语言。开发 Swift 的目的是找到 C、C++和 Objective-C 等基于 C 的语言的替代品。凭借其语法的表达性质,Swift 拥有开发人员想要的现代功能,并使 iOS 应用开发更容易。

有各种资源可用于学习 Swift 然而,苹果公司开发的应用 Swift Playgrounds 可以让你以有趣和互动的方式学习 Swift。目前该应用适用于 iPad 和 Mac,可以从 App Store 下载,如图 1-3 所示。

图 1-3

斯威夫特游乐场

Xcode 简介

除了支持在 MacOS 系统上开发之外,Xcode 还是由 Apple 开发的集成开发环境(IDE ),它拥有您在所有 Apple OS 平台上开始 iOS 开发所需的一切。它包括代码编辑器、调试器等功能。它还附带了一个模拟器,使您能够在真实的 iOS 设备上构建和测试您的应用,而不需要物理 iOS 设备。

在接下来的几节中,我将向您展示如何安装 Xcode 并使用它来构建和部署 iOS 应用。

安装 Xcode 12

我将在 macOS Big Sur 上安装 Xcode 12,这两个版本目前分别是 Xcode 和 macOS 的最新版本。要安装,去 Mac 上的 App Store 搜索 Xcode,如图 1-4 所示。

图 1-4

App Store 上的 Xcode 搜索结果

单击安装图标,等待安装完成。

  • 如果您收到类似“Xcode 不能安装在“Macintosh HD”上,因为需要 macOS X 版本或更高版本”的错误,请在尝试安装之前更新您的 MAC OS。

安装后,启动 Xcode,你应该会看到一个欢迎页面,如图 1-5 所示。

图 1-5

启动 Xcode

接下来,我将通过创建一个示例应用向您展示如何使用 Xcode 创建应用。

创建应用

安装 Xcode 后,您就可以开始构建 iOS 应用了。我将从使用 Xcode 提供的应用模板开始,然后添加自定义代码来定制应用。

iOS 应用模板

Xcode 提供了样本模板,可以轻松开始构建应用。这些模板可以通过创建一个新的 Xcode 项目来访问(图 1-5 ),并显示不同的可用模板。对于我正在构建的样例 app,我会选择 iOS 和 App,如图 1-6 所示。

图 1-6

为 Xcode 项目选取模板

如果这是你第一次使用 Xcode,会有提示用 Apple ID 登录,如图 1-7 所示。

图 1-7

苹果登录新 Xcode 项目

登录并将 Apple ID 链接到 Xcode 后,将会提示您配置新 Xcode 项目的详细信息。示例如图 1-8 所示。

图 1-8

填写新 Xcode 项目的详细信息

创建之前,必须选择工作站上保存应用的文件夹位置。一旦完成,就创建了一个应用,如图 1-9 所示。

图 1-9

已创建示例应用项目模板

如图 1-9 所示,由于在图 1-8 中创建项目时选择了 Swift 语言,所以应用模板是用 Swift 语言编写的。

让我们看看现成的 Swift 代码,看看它在做什么。

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Listing 1-1ContentView.swift

清单 1-1 中的代码片段负责显示在 iOS 设备上的视图;正如所见,这个 iOS 应用模板简单地打印出 “你好,世界!”

import SwiftUI

@main
struct SampleAppApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Listing 1-2SampleAppApp.swift

清单 1-2 显示了应用的入口点,如图所示,它通过调用 ContentView() (在不同的文件 ContentView.swift 中定义)来运行应用,如清单 1-1 所示。

Xcode 实时预览

在配置项目时选择 SwiftUI 界面,可以在代码中对内容视图进行更改时实时预览应用。

让我们来看一个默认应用的预览。从运行目标菜单中,选择您想要使用的 iOS 模拟器,如图 1-10 所示。

图 1-10

选择 iOS 模拟器

选择 iPhone 11 模拟器,预览显示在模拟的 iPhone 11 上,如图 1-11 所示。如图所示,实时预览让您能够在运行构建之前查看应用视图的外观。当在代码中对应用视图进行更改时,预览也会更新。

图 1-11

iPhone 11 模拟器上的默认应用预览

与 Swift 一起发展

至此,您已经使用了创建 Xcode 项目时作为所选模板的一部分提供的默认应用,现在让我们添加一个自定义 Swift 代码。

用清单 1-3 中的代码替换content view . swift?? 的内容。

import SwiftUI

struct ContentView: View {
    @State private var date = Date()

    let dateRange: ClosedRange<Date> = {
        let calendar = Calendar.current

        let startComponents = DateComponents(year: 2021, month: 1, day: 1)
        let endComponents = DateComponents(year: 2021, month: 12, day: 31, hour: 23, minute: 59, second: 59)
        return calendar.date(from:startComponents)!
            ...
            calendar.date(from:endComponents)!
    }()

    var body: some View {
        DatePicker(
            "Start Date",
            selection: $date,
            in: dateRange,
            displayedComponents: [.date, .hourAndMinute]
        )
        .padding(.all)
        .datePickerStyle(GraphicalDatePickerStyle())
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Listing 1-3Sample Application Code

示例应用是一个简单的虚拟日历应用,允许您选择日期和该日期内的时间。接下来,您将为此应用添加一个图标。

添加应用图标

应用图标是应用的可视化表示,显示在主屏幕、App Store 和各种其他位置,如设置和搜索结果。由于用途多样,苹果要求应用图标有不同的大小。

进入 Assets.xcassets ,拖动图标到各自的槽位,即可添加 App 图标,如图 1-12 所示。

图 1-12

添加应用图标

构建应用

我们已经创建了一个定制的示例应用代码,并为该应用添加了一个图标。我们已经准备好了应用的所有基本构件。现在我们将构建应用并在 iOS 设备上运行它。

基于物理 iPhone 构建

让我们看看这个应用在物理 iOS 设备上是什么样子的,比如 iPhone。

要在物理 iPhone 上构建应用,必须将其插入用于开发的 Mac 工作站。一旦将设备插入工作站,就可以选择它作为构建目标。示例如图 1-13 所示。

图 1-13

选择用于构建的物理 iOS 设备

要在已连接的物理 iOS 设备上开始构建,请单击设备选项左侧的播放标志按钮(图 1-13 )。可能会显示 iOS 钥匙圈提示,如图 1-14 所示。这需要 Mac 工作站密码(不是你的 Apple ID 密码)。

图 1-14

Apple 钥匙串登录提示

  • 您需要在 Xcode ➤偏好设置下将您的 Apple 帐户添加到 Xcode,以建立 Apple 开发团队。

  • 请确定您的 iPhone 已解锁,以便 Xcode 连接到它并安装示例应用。如果这是你第一次将你的 iPhone 插入 Mac 工作站,你会得到一个提示来信任工作站。

  • 您可能还需要通过设置➤通用➤设备管理来信任 iPhone 上的应用开发人员。

构建完成后,带有图标的新应用就会安装在 iPhone 上。

图 1-15 显示了在物理 iPhone 上启动应用时的用户界面示例。

图 1-15

在物理 iPhone 上启动示例应用

基于 iOS 模拟器构建

就像在物理设备上构建和运行应用一样,让我们在模拟器上运行应用。

要在模拟器上构建,应该像选择物理 iOS 设备一样选择目标设备模拟器,并开始构建,单击设备选择左侧的播放符号按钮,如图 1-13 所示。

一旦构建完成,模拟器将显示安装了应用的模拟 iPhone。使用光标滚动模拟 iPhone 的页面,并启动已安装的应用。图 1-16 显示了应用的图标以及在 iPhone 11 模拟器上启动时的样子。

图 1-16

在 iPhone 11 模拟器上启动示例应用

Xcode 命令行工具

到目前为止,我已经向您展示了如何使用 Xcode 用户界面构建应用;但是,您也可以通过命令行界面使用 Xcode 的命令行工具 xcodebuild 与 Xcode 进行交互。

xcodebuild 允许您从命令行对 Xcode 项目执行构建、测试和归档等任务。有了它,您可以在命令行上从用户界面执行我们之前执行的所有任务,这为自动化打开了大门。

它预装了 Xcode,所以在 macOS 工作站上安装它不需要额外的操作。在您的工作站上运行xcodebuild -usage命令来查看一些基本的使用信息,如清单 1-4 所示。

$ xcodebuild -usage
Usage: xcodebuild [-project <projectname>] [[-target <targetname>]...
       xcodebuild [-project <projectname>] -scheme <schemeName> [-destination <destinationspecifier>]...
       xcodebuild -workspace <workspacename> -scheme <schemeName> [-destination <destinationspecifier>]...
       xcodebuild -version [-sdk [<sdkfullpath>|<sdkname>] [-json] [<infoitem>] ]
       xcodebuild -list [[-project <projectname>]|[-workspace <workspacename>]] [-json]
       xcodebuild -showsdks [-json]

Listing 1-4xcodebuild -usage truncated output

要查看包括所有可用选项在内的更多使用细节,运行xcodebuild -help并查看输出,如清单 1-5 所示。

$ xcodebuild -help
Usage: xcodebuild [-project <projectname>] [[-target <targetname>]...
...
       xcodebuild -version [-sdk [<sdkfullpath>|<sdkname>] [-json] [<infoitem>] ]
       xcodebuild -list [[-project <projectname>]|[-workspace <workspacename>]] [-json]
       xcodebuild -showsdks [-json]
...

Options:
    -usage                        print brief usage
    -help                         print complete usage
    -verbose                      provide additional status output
    -license                      show the Xcode and SDK license agreements
    -checkFirstLaunchStatus       Check if any First Launch tasks need to be performed
    -runFirstLaunch               install packages and agree to the license
    -project NAME                 build the project NAME
    -target NAME
...

Listing 1-5xcodebuild -help truncated output

您可以使用 xcodebuild 在前面几节创建的示例应用中导航,如清单 1-6 和 1-7 所示。

首先,您可以列出关于示例应用项目的所有信息。

  • 您必须在项目和工作区目录中才能运行以下命令。
$ xcodebuild -list -project SampleApp.xcodeproj
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -list -project SampleApp.xcodeproj

User defaults from command line:
    IDEPackageSupportUseBuiltinSCM = YES

Information about project "SampleApp":
    Targets:
        SampleApp
        SampleAppTests
        SampleAppUITests

    Build Configurations:
        Debug
        Release

    If no build configuration is specified and -scheme is not passed then "Release" is used.

    Schemes:
        SampleApp

Listing 1-6Listing all the information about a project

接下来,您可以在工作区中列出方案。

$ xcodebuild -list -workspace project.xcworkspace
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -list -workspace project.xcworkspace

User defaults from command line:
    IDEPackageSupportUseBuiltinSCM = YES

Information about workspace "SampleApp":
    Schemes:
        SampleApp

Listing 1-7Listing all schemes in your workspace

摘要

本章向您展示了 iOS 应用开发的基本构件;通过构建自己的应用并将其部署到实际的 iOS 设备和 iOS 模拟器上,您获得了实践经验。

在下一章中,我们将更进一步,探索如何将构建的应用提交到 App Store Connect 进行分发和/或最终提交到 Apple 的 App Store。

二、从 Xcode 到 App Store Connect

本章面向 iOS 应用开发初学者;如果你是 iOS 开发者或者有开发 iOS 应用的经验,可以跳过。

在前一章中,我们看到了如何使用 Xcode 在物理 iPhone 设备和模拟器上构建和运行应用。我们将进一步探索如何通过上传到 App Store Connect 来分发之前构建的应用。

  • 第 1 (图 1-2 )章中涵盖的苹果开发者计划账户需要执行本章中的步骤。

标识符

在将应用版本上传到 App Store Connect 之前,必须为应用注册一个标识符。标识符用于唯一地标识一个应用,以便没有两个应用共享一个标识符。

可以从苹果开发者计划门户创建新的标识符。从门户可以进入证书、标识&简介页面,如图 2-1 所示。

图 2-1

应用开发者计划门户

可以创建一个新的标识符,如图 2-2 所示。

图 2-2

创建新的标识符

用户可以创建不同类型的标识符,如图 2-3 所示。应该创建一个应用 ID。

图 2-3

选择标识符类型

目前有两种类型的应用 id。选择如图 2-4 所示的类型。

图 2-4

选择应用 ID 类型

应该提供描述和 ID 名称。示例如图 2-5 所示。

图 2-5

提供 ID 名称和描述

  • 记下您在这里使用的 ID 名称。

应用商店连接

App Store Connect 是一个平台,用于管理 App Store 上应用的所有信息。最重要的是,应用通过 App Store Connect 提交到苹果的 App Store。您可以通过 Apple 开发者计划帐户访问 App Store Connect。入口如图 2-6 所示。

图 2-6

应用商店连接

必须先创建应用,然后才能将应用内容上传到 App Store Connect。这将作为应用在 App Store 上的占位符,并且可以在此配置应用的所有信息。

要创建应用,请导航至 App Store 连接应用页面并创建一个应用,如图 2-7 所示。

图 2-7

创建新应用

要创建应用,选择之前在图 2-5 中创建的包 ID,并提供应用详细信息。图 2-8 显示了我提供的申请细节。

图 2-8

提供新的应用详情

  • 您的应用名称必须是唯一的,并且不能已经存在于 App Store 中。

一旦创建了应用,就会显示一个登录页面,如图 2-9 所示,在这里你可以配置更多关于你的应用的细节,比如截图和其他元数据信息。

图 2-9

App Store Connect 中的新应用

截图和应用详细信息

现在应用已经创建,您可以继续添加将在 App Store 上显示的应用截图以及应用的其他相关信息。

尽可能多地添加应用的详细信息。为应用输入的一些信息是截图、应用类别、定价和可用性、应用隐私、版本发布等。正如我们将在下图中看到的那样。

虽然有各种工具可以创建屏幕截图,但当应用在模拟器上运行时,iOS 模拟器可以用于截图。图 2-10 显示了在 App Store Connect 上添加截图的位置。

图 2-10

在 App Store Connect 中添加新应用的屏幕截图

图 2-11 显示了如何配置应用类别的示例。通过从左侧菜单中选择常规➤应用信息,可以访问应用类别。

图 2-11

为您的应用配置类别

图 2-12 显示了如何配置应用的价格和可用性。

图 2-12

为您的应用配置价格和可用性

图 2-13 显示了如何配置应用的隐私策略。

图 2-13

为您的应用添加隐私策略

图 2-14 显示了发布应用新版本的配置示例。

图 2-14

为应用添加版本发布设置

从 Xcode 上传构件

此时,您已经在 App Store Connect 中创建了一个应用,并配置了所有应用元数据。现在您可以从 Xcode 上传构建到 App Store Connect 了。

为此,您需要创建一个完整的应用归档。我们通过从模拟器列表中选择任何 iOS 设备来实现,如图 2-15 所示。

图 2-15

为完整的应用档案选择模拟器

在创建归档之前,验证 Xcode 上配置的捆绑包标识符是否与 App Store Connect 上配置的捆绑包 ID 相匹配,如图 2-5 所示。这一点可以在 Xcode 上 app 的通用设置中验证,如图 2-16 。

图 2-16

验证捆绑 ID

一旦验证了包 ID,就可以创建完整的归档文件了。创建档案时,选择产品档案,如图 2-17 所示。

图 2-17

创建完整的应用归档

归档完成后,会弹出一个新窗口,如图 2-18 所示,显示已创建的归档。还将列出多个归档文件(如果可用),以及该归档文件的版本和创建日期。

接下来选择分发 App ,如图 2-18 所示。

图 2-18

要分发的应用归档

要分发应用,您必须选择分发方式。由于这里的目标是上传到 App Store,你选择 App Store Connect ,如图 2-19 所示。

图 2-19

将应用上传到 App Store Connect

若要将 iOS 应用上传到 App Store Connect,需要 Apple 分发证书。如果 Xcode 找不到证书,例如,如果您是第一次上传应用,它会尝试为您创建一个新的,您会得到如图 2-20 所示的提示。

图 2-20

创建 Apple 分发证书

Xcode 生成证书后,它会将证书储存在 Keychain 中,但也让您有机会导出证书 p12 文件以便安全保管。你会得到如图 2-21 所示的提示。

图 2-21

导出 Apple 分销证书

  • 导出证书不是必需的,但建议导出。如果您选择不导出证书,可以单击“下一步”跳过。

上传开始前,会提示你 App Store 分发选项,比如包含 iOS 内容的位代码,上传 App 符号;选择这些选项。

此外,系统会提示您选择签名选项。选择让 Xcode 自动管理签名的选项。

  • 如果您已经有要使用的证书和预置描述文件,您可以手动管理签名。

一旦应用上传开始,你应该会看到一个进度条,如图 2-22 所示。

图 2-22

正在上传应用

一旦上传完成并且没有错误,您将会看到上传成功消息,如图 2-23 所示。

图 2-23

应用上传完成

既然上传成功,请等待一段时间让应用在 App Store Connect 上可见,当您的构建在 App Store Connect 上就绪时,您通常会收到电子邮件通知。

接下来,我们将探讨如何对上传的新应用进行测试,最后,如何提交应用进行审查。

测试和发布

当上传的版本在 App Store Connect 上可用时,您可以在最终提交到 App Store 之前对应用进行可选的测试。让我们来探索一下如何在苹果的 App Store Connect 上完成这些。

TestFlight 软件

测试版测试不是 iOS 应用开发流程中的必要步骤。然而,苹果提供了一个名为 TestFlight 的工具,可以用于 beta 测试。通过 TestFlight,你可以邀请实际用户下载并安装你的应用到他们的设备上,以便在公开发布之前收到反馈。

要为 beta 测试添加测试人员,您可以转到 TestFlight 选项卡并选择 build。您可以选择添加单个测试人员或一组测试人员,并向测试人员提供信息,如图 2-24 所示。

图 2-24

添加生成测试信息

如果您选择添加单个测试人员的选项,您将得到一个弹出窗口,如图 2-25 所示,您应该在这里提供测试人员的姓名和联系方式。

图 2-25

向构建中添加测试人员

添加测试人员后,添加测试信息并提交测试进行审核,如图 2-26 所示。

图 2-26

提交 beta 测试以供审查

应用提交

该流程的最后一步是提交应用进行审核。滚动到 App Store Connect 上的 Build 部分,要提交你的应用进行审核,首先选择一个已经上传到 App Store Connect 的 Build,如图 2-27 所示。

图 2-27

选择上传的版本

一旦选择并添加了一个构件,提交审查按钮被激活,如图 2-28 所示。

图 2-28

提交应用进行审核

在此提交应用会在应用可用之前启动 Apple 的审查。

摘要

本章在前一章的基础上总结了 iOS 开发的基础知识,并向您展示了如何与 App Store Connect 进行交互,以便从您的工作站上传应用版本、执行 beta 测试以及提交供审查。

在下一章中,我们将通过回顾 DevOps、AWS 云的基础知识来了解 DevOps,您将了解不同的 AWS DevOps 产品。

三、亚马逊网络服务(AWS)上的 DevOps

业界对 DevOps 有不同的定义,但所有这些定义大多指向相同的原则。AWS 对 DevOps 的定义如下:

DevOps 是文化哲学、实践和工具的结合,它提高了组织高速交付应用和服务的能力:以比使用传统软件开发和基础设施管理流程的组织更快的速度发展和改进产品

DevOps 概念的主要目标是改进软件开发生命周期。为了实现这一点,它引入了不同的方法、工具、过程等。

AWS 为 DevOps 的各个方面提供了丰富的工具,它还与第三方工具集成,为用户在 AWS 上实践 DevOps 提供了广泛的选择。在这一章中,我将介绍一些基本的 AWS 云概念,然后我们将探索 AWS 上用于实践 DevOps 的主要工具和技术。我将介绍这些服务,并演示如何在 AWS 管理控制台上开始使用这些服务。我们还将介绍一些与第三方工具的常见集成。

AWS 上的持续集成

持续集成的概念是让开发人员在源代码控制管理工具中定期合并代码,并频繁运行自动化测试。这允许您快速检测软件问题,从而提高软件交付的整体质量。

让我们在接下来的章节中探索 AWS 提供的不同的持续集成工具。

AWS 代码提交

简而言之,AWS CodeCommit 是一个托管的私有 git 存储库服务。作为托管 AWS 服务,您不需要管理底层硬件或配置来支持托管私有 git 存储库,因此它是安全的和高度可伸缩的。作为一个 git 存储库,它支持标准的 git 功能,因此它可以与现有的基于 git 的工具一起工作,比如 git cli、GUI 客户端等。

使用 AWS 代码提交的好处

使用 AWS CodeCommit 作为您的私有 git 存储库有很多好处;所有这些都可以归纳为以下五个要点:

  1. 它具有高可用性和耐用性。

  2. 数据受到保护和安全,静态和传输中的数据都经过加密。

  3. 可以定义细粒度的访问控制。

  4. 团队成员之间协作的便利性。

  5. 与其他 AWS 自动化工具集成以扩展其功能。

创建代码提交存储库

创建 CodeCommit 存储库有多种方式,例如通过 AWS 管理控制台、AWS CLI、AWS SDKs 等。;然而,我将展示开始使用 AWS 管理控制台界面的最简单方法。

首先登录 AWS 管理控制台,在搜索栏中搜索 CodeCommit,如图 3-1 所示。

图 3-1

AWS 管理控制台上的 AWS 代码提交搜索

启动 CodeCommit 页面的另一个选项是从 AWS 管理控制台的开发者工具部分选择 CodeCommit,如图 3-2 所示。

图 3-2

从开发人员工具部分选择 CodeCommit

启动 CodeCommit 网页后,创建一个引用图 3-3 的存储库。

图 3-3

开始代码提交存储库创建

提供库名,可选描述,选择创建,如图 3-4 所示。

图 3-4

创建代码提交存储库

创建存储库之后,下一步是连接到您的存储库并开始使用它,如图 3-5 所示。要进行连接,您需要使用现有的基于 git 的工具。

图 3-5

连接到代码提交存储库

  • 我们将在第六章中更详细地介绍代码提交连接。

AWS 代码构建

AWS CodeBuild 是云上的托管构建服务器。它提供了一个计算环境来编译代码,运行测试和产品工件。CodeBuild 从源代码提供者处获取源代码,并执行 YAML 规范文件(通常称为 Buildspec)中定义的操作。对于源代码提供者,CodeBuild 目前支持亚马逊 S3、AWS CodeCommit、GitHub、Bitbucket 和 GitHub Enterprise。

创建代码构建项目

从 AWS 管理控制台,在搜索栏中搜索 CodeBuild,如图 3-6 所示。

图 3-6

AWS 管理控制台上的 AWS 代码构建搜索

  • CodeBuild 项目也可以从 AWS CLI、AWS SDKs 和其他基础设施作为代码工具创建。

您也可以在 AWS 管理控制台的开发者工具部分选择 CodeBuild,如图 3-2 所示。

在 CodeBuild 页面上,创建一个构建项目,如图 3-7 所示。

图 3-7

开始创建代码构建项目

一个 CodeBuild 项目支持不同的源代码。将由 CodeBuild 编译或构建的源代码将存储在这个源代码库中。对于不需要源代码的构建,不需要配置源代码。这种构建的一个例子是当构建被配置为连接到外部位置以获取构建所需的资源时。

如图 3-8 所示,没有为我将要创建的项目配置任何源。

图 3-8

正在配置代码生成项目的源代码

如前所述,CodeBuild 项目提供了一个使用容器映像执行构建操作的计算环境。您可以选择使用托管 AWS 代码构建映像或提供自定义 docker 映像。如图 3-9 所示,我将使用托管代码构建映像。

图 3-9

代码构建项目计算环境

CodeBuild 项目需要生成规范。当使用项目的源代码提供者时,YAML 构建规范文件可以存储在代码存储库中,并且在项目中配置名称和位置,默认情况下 CodeBuild 将查找文件名 buildspec.yaml 。构建规范命令也可以直接提供给项目,如果项目没有配置任何源代码,这是特别需要的,我们正在创建的 CodeBuild 项目就是这种情况。

下面的清单显示了一个示例构建规范。定义的每个阶段按顺序执行,每个阶段中的命令也按顺序执行。

version: 0.2
phases:
  install:
    commands:
      - echo Entered the install phase...
      - apt-get update -y
      - apt-get install -y maven
  pre_build:
    commands:
      - echo Entered the pre_build phase...
  build:
    commands:
      - echo Entered the build phase...
      - echo Build started on `date`
  post_build

:
    commands:
      - echo Entered the post_build phase...
      - echo Build completed on `date`

Listing 3-1CodeBuild build specification

复制此示例,并作为构建规范提供,如图 3-10 所示。

图 3-10

代码构建构建规范

  • 您可能需要切换到编辑器模式来查看页面,以输入构建规范。

将其余设置保留为默认设置,创建 CodeBuild 项目,如图 3-11 所示。图 3-11 中选中的 CloudWatch 日志选项确保构建日志流至 Amazon CloudWatch 以方便访问,并为进一步的日志处理打开大门。

图 3-11

创建代码构建项目

AWS 程式码人工因素

AWS CodeArtifact 是一个工件存储库,用于存储、发布和共享软件开发过程中使用的软件包。这是一项全面管理的服务;因此,不需要管理基础架构和许可证。

使用 AWS CodeArtifact,您可以发布私有包供开发人员使用,也可以将其配置为从公共工件存储库中获取。当配置为从公共工件库中获取时,使用 AWS CodeArtifact 的额外优势是定义访问控制和验证软件包的能力。它与常见的包管理器一起工作,如 Maven、Gradle、npm、yarn、twine、pip 和 NuGet。

创建代码工件存储库

让我们看看如何创建 AWS 代码工件库。我将在 AWS 管理控制台的开发者工具部分选择 CodeArtifact ,如图 3-2 所示,然后开始创建库,如图 3-12 所示。

图 3-12

开始创建 CodeArtifact 仓库

  • AWS CodeArtifact 也可以作为代码工具从 AWS CLI、AWS SDKs 和其他基础设施中创建。

您将看到如图 3-13 所示的页面,在这里您可以填写存储库名称。如果要配置该库连接上游公共库,也可以在这里配置上游库,如图 3-13 所示。

图 3-13

提供存储库详细信息

CodeArtifact 中有一个域的概念。这是存储库的逻辑分组,每个 CodeArtifact 存储库必须是域的一部分。一个域也可以在另一个 AWS 帐户中,这使得在多帐户 AWS 环境中管理大量代码工件存储库变得容易。可以创建或选择一个域,如图 3-14 所示。

图 3-14

创建存储库域

创建域后,下一步是检查和创建存储库,如图 3-15 所示。

图 3-15

审查和创建 CodeArtifact 存储库

对于初始连接,会显示不同通用软件包管理器的连接说明,例如,创建后的 npm。

AWS 上的连续交付

正如上一节所讨论的,持续集成涵盖了开发人员如何在源代码控制管理工具中定期合并代码,并运行频繁的自动化测试。连续交付通过部署代码变更而更进一步。代码变更可以被部署到开发和/或测试环境中,这确保您总是拥有一个已经被构建和测试的生产就绪的工件。

AWS 代码部署

AWS CodeDeploy 是一项自动化软件部署服务。借助 CodeDeploy,您可以自动部署到在 Amazon Elastic Compute Cloud(Amazon EC2)实例、Amazon Elastic Container Service(Amazon ECS)、本地服务器和 AWS Lambda 功能上运行的应用。

要使用 CodeDeploy,您需要在一个 YAML 规范文件中定义应用应该如何部署,这个文件通常被称为app spec . YAML;CodeDeploy 使用这个规范文件来完成应用部署。对于 Amazon EC2 和内部部署,CodeDeploy 代理必须安装在应用服务器上,以便 CodeDeploy 管理部署,但对于 Amazon ECS 和 AWS Lambda 等其他计算平台,CodeDeploy 代理不使用,因为它们是托管的 AWS 服务。

应用规范文件根据目标计算平台采用不同的形式,例如 Amazon EC2、AWS Lambda 等。让我们看看不同计算平台的规范文件示例。

  • 清单 3-3 和 3-4 中的钩子部分只有在您运行带有 AWS Lambda 函数的验证脚本作为部署的一部分时才需要。在这些例子中,我引用的 AWS lambda 函数应该已经存在于具有 CodeDeploy 的同一个 AWS 帐户和 AWS 区域中。

清单 3-2 显示了部署到 Amazon EC2 或本地服务器的示例规范文件。

version: 0.0
os: linux
files:
  - source: Config/config.txt
    destination: /webapps/Config
  - source: source
    destination: /webapps/myApp
hooks:
  BeforeInstall:
    - location: Scripts/UnzipResourceBundle.sh
    - location: Scripts/UnzipDataBundle.sh
  AfterInstall:
    - location: Scripts/RunResourceTests.sh
      timeout: 180

  ApplicationStart:
    - location: Scripts/RunFunctionalTests.sh
      timeout: 3600
  ValidateService:
    - location: Scripts/MonitorService.sh
      timeout: 3600
      runas: codedeployuser

Listing 3-2Example appspec for Amazon EC2 or on-premises deployment

清单 3-3 显示了一个 AWS Lambda 功能部署的示例规范文件

version: 0.0
Resources:
  - myLambdaFunction:
      Type: AWS::Lambda::Function
      Properties:
        Name: "myLambdaFunction"
        Alias: "myLambdaFunctionAlias"
        CurrentVersion: "1"
        TargetVersion: "2"
Hooks:
  - BeforeAllowTraffic: "ValidateBeforeTrafficShift"
  - AfterAllowTraffic: "ValidateAfterTrafficShift"

Listing 3-3Example appspec for AWS Lambda deployment

清单 3-4 显示了一个 AWS Lambda 功能部署的示例规范文件。

version: 0.0
Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: "arn:aws:ecs:us-east-1:111222333444:task-definition/my-task-definition-family-name:1"
        LoadBalancerInfo:
          ContainerName: "SampleApplicationName"
          ContainerPort: 80
Hooks:
  - BeforeInstall: "ValidateBeforeInstall"
  - AfterInstall: "ValidateAfterInstall"
  - AfterAllowTestTraffic: "ValidateAfterTestTraffic"
  - BeforeAllowTraffic: "ValidateBeforeProdTraffic"
  - AfterAllowTraffic: "ValidateAfterProdTraffic"

Listing 3-4Example appspec for Amazon ECS deployment

AWS 代码管道

使用 AWS CodePipeline,您可以按照阶段和操作的顺序编排和自动化组成软件发布过程的所有步骤和操作。CodePipeline 集成了各种 AWS 服务和第三方工具,使您能够创建从源代码到部署的整个软件交付过程自动化的管道。

使用 AWS 代码管道创建 CICD 管道

要开始创建管道,我将在 AWS 管理控制台的开发者工具部分选择代码管道,如图 3-2 所示,然后开始创建管道,如图 3-16 所示。

图 3-16

开始创建管道

  • AWS 代码管道也可以通过 AWS CLI、AWS SDKs 和其他基础设施作为代码工具来创建。

因为管道将代表您执行操作,所以它需要一个 service IAM 角色来定义管道在 AWS 帐户中拥有的权限。在 AWS 管理控制台上创建管道时,可以为您创建所需的 IAM 角色,或者您可以选择现有的 IAM 角色,如图 3-17 所示。

图 3-17

创建代码管道服务角色

现在,您开始定义管道的结构。管道的第一级是源级,它将定义应用源代码的存储位置。对于源代码阶段,AWS CodePipeline 支持亚马逊 ECR、AWS CodeCommit、亚马逊 S3 和第三方工具,如 Bitbucket 和 GitHub。在图 3-18 中,AWS CodeCommit 被配置为管道的源。

图 3-18

将 AWS 代码提交配置为管道源阶段

  • 此处提供的分支名称应该与 CodeCommit 存储库中的有效分支相匹配;否则管道将会失败。

接下来,我们配置一个构建阶段。对于构建阶段,CodePipeline 支持 AWS CodeBuild、CloudBees、Jenkins 和 TeamCity。图 3-19 显示了在构建阶段使用 AWS CodeBuild。

图 3-19

将 AWS 代码构建配置为管道构建阶段

构建阶段之后是部署阶段。在部署阶段,从构建阶段检索构建的工件,然后进行部署。您可以有多个代表不同环境的部署阶段。

CodePipeline 集成了各种 AWS 服务和工具,以支持您的应用部署。

图 3-20 显示了在 AWS 管理控制台上创建部署阶段时支持的部署提供者。

图 3-20

代码管道部署提供程序

虽然代码管道在初始创建期间至少需要两个阶段,但部署阶段不是必需的,可以在管道初始创建期间跳过。参见图 3-21 了解如何跳过部署阶段。

图 3-21

跳过添加部署阶段

在配置完所有阶段并与所需工具集成之后,就可以创建管道了。如图 3-22 所示,您可以查看并创建管道。

图 3-22

查看和创建管道

创建管道后,它将首次运行并执行所有已配置的阶段。如图 3-23 所示,配置了两个阶段(Source 和 Build);管道从 AWS CodeCommit 获取源工件,并使用 AWS CodeBuild 构建它。

图 3-23

成功的管道运行

基础设施作为代码

DevOps 的一个关键原则是部署自动化,但这个自动化概念不仅适用于应用,也适用于基础架构自动化。将基础架构定义为类似代码的应用,可以实现自动化的基础架构部署,从而大大减少部署时间,限制人为错误,并允许重用。通过将基础设施定义为代码,源代码控制也可以用于管理基础设施的生命周期。

我们将探讨 AWS 的基础设施即代码(IaC)产品,这将帮助您了解如何轻松地在 AWS 上自动配置资源。

AWS 云阵

AWS CloudFormation 是一项允许您在模板中定义 AWS 资源的服务,该模板可以用 jSON 或 YAML 语言编写。在 CloudFormation 中,您定义您的目标架构和模板中所有不同组件的集成,然后创建一个堆栈来提供资源。

可以在 AWS 控制台上评估 AWS 云的形成,如图 3-24 所示。

图 3-24

从 AWS 控制台访问 CloudFormation 服务

要创建 CloudFormation 堆栈,您必须有一个模板来定义您将供应的资源。CloudFormation 具有不同的部分和必须遵守的定义的剖析,以确保当使用模板创建堆栈时,CloudFormation 知道如何处理一个或多个资源的生命周期。

清单 3-5 中给出的模板显示了启用版本控制的 S3 存储桶的定义。此外,S3 存储桶的名称是在运行时动态生成的,它由 AWS 帐号和将在其中创建堆栈的 AWS 区域组成,然后存储桶名称作为 CloudFormation 堆栈的输出进行传递。

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Sample S3 Bucket with Versioning Enabled'
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${AWS::AccountId}-${AWS::Region}-bucket
      VersioningConfiguration:
        Status: Enabled
    DeletionPolicy: Retain
Outputs:
  BucketName:
    Value: !Ref S3Bucket
    Description: S3 Bucket Name

Listing 3-5CloudFormation template

从搜索栏或 AWS 管理控制台主页访问 CloudFormation 控制台后,要从定义的模板创建 CloudFormation 堆栈,请选择创建堆栈选项,如图 3-25 所示。

图 3-25

创建云形成堆栈

  • AWS CloudFormation 堆栈也可以通过 AWS CLI、AWS SDKs 和其他基础设施作为代码工具来创建。

  • 图 3-25 显示了在账户和区域中没有现有的云形成堆栈的情况。如果存在现有的 CloudFormation 堆栈,它们将被列出,但“创建堆栈”按钮仍将被启用。

  • 当创建堆栈动作为您提供堆栈创建选项来创建新的现有的资源时,选择创建新的资源

这将启动创建工作流,第一步是提供您想要启动的模板。图 3-26 显示了如何上传已经创作的模板。

图 3-26

提供云形成模板

  • 清单 3-5 中显示的模板保存在一个名为 s3.yaml 的文件中,用于创建堆栈。

在提供这个模板并选择下一个的之后,CloudFormation 处理模板并解析错误和无效条目。一旦模板被验证,你就可以配置栈名和参数(如果有的话),如图 3-27 所示。

图 3-27

配置堆栈详细信息

理想情况下,下一步也是最后一步是创建堆栈。然而,在 CloudFormation 中有一个称为变更集的概念,它允许您可视化和检查将对 CloudFormation 堆栈中的资源进行的变更,即,将被添加、删除或只是修改的资源。图 3-28 显示了继续创建堆栈或创建变更集的选择。

图 3-28

创建变更集

如果你只是选择创建堆栈,CloudFormation 就会开始创建你的资源。如果您选择创建变更集,则在创建变更集之前,将需要其他配置,如变更集名称。图 3-29 显示了使用变更集配置的默认值。

图 3-29

配置变更集

更改集将允许您查看将要进行的配置更改的详细信息。图 3-30 显示只添加一个资源,一个 S3 存储桶。这是因为这是一个初始的栈创建,而清单 3-5 中的云形成模板只定义了一个 S3 资源。

图 3-30

用于堆栈创建的更改集

如果您对更改不满意,您可以删除更改集,并且不会发生任何操作。当执行变更集时,资源创建或更新开始。图 3-31 显示了根据图 3-30 中执行的变更集创建的云形成堆栈。

图 3-31

堆栈创建完成

AWS 云开发套件(CDK)

CDK 是一个作为代码框架的开源基础设施,允许您用熟悉的编程语言(如 TypeScript、JavaScript、Python、Java 和 C#)定义 AWS 资源。这使得开发人员更容易将基础设施供应集成到现有的软件开发生命周期中。

当在 CDK 定义和部署基础设施时,CDK 使用 CloudFormation 来部署资源,因此它负责将 CDK 脚本转换为相应的 CloudFormation 模板来部署资源。

自动气象站 CDK 安装

AWS CDK 工具包可以与节点程序包管理器(npm)一起安装。清单 3-6 显示了 AWS CDK 工具包的安装示例。

$ sudo npm install -g aws-cdk
/usr/bin/cdk -> /usr/lib/node_modules/aws-cdk/bin/cdk

> aws-sdk@2.932.0 postinstall /usr/lib/node_modules/aws-cdk/node_modules/aws-sdk
> node scripts/check-node-version.js

+ aws-cdk@1.110.0
added 181 packages from 216 contributors in 8.404s

Listing 3-6AWS CDK toolkit installation

安装 CDK 之后,您可以使用命令cdk --version检查 CDK 版本来测试安装。

  • 根据安装时间的不同,版本可能有所不同。

与 CDK 一起部署基础设施

正确安装 CDK 后,您可以开始用任何受支持的 CDK 语言创建您的基础设施。在清单 3-7 中,我展示了如何用 Python 初始化一个 CDK 应用和一个输出片段。

$ mkdir hello-cdk
$ cd hello-cdk
$ cdk init app --language python
Applying project template app for python

# Welcome to your CDK Python project!

This is a blank project for Python development with CDK.

The `cdk.json` file tells the CDK Toolkit how to execute your app.

This project is set up like a standard Python project. The initialization process also creates a virtualenv within this project, stored under the `.venv` directory. To create the virtualenv it assumes that there is a `python3` (or `python` for Windows) executable in your path with access to the `venv` package. If for any reason the automatic creation of the virtualenv fails, you can create the virtualenv manually.

To manually create a virtualenv on MacOS and Linux:

$ python3 -m venv .venv


Listing 3-7Initialize CDK Application

当一个 Python CDK 项目被初始化时,它会创建一个 Python 虚拟环境,如清单 3-7 所示。它还会创建一个 requirement.txt 文件,您可以在其中定义应用依赖关系。我将激活 Python 虚拟环境并安装依赖项,如清单 3-8 所示。

$ source .venv/bin/activate
(.venv) $ python -m pip install -r requirements.txt

Listing 3-8Installing CDK project dependencies

在 CDK,基础设施是以堆栈的形式定义的,一个 CDK 应用必须至少包含一个堆栈,才能部署资源。当 CDK 将其脚本转换为 CloudFormation 时,它会为每个 CDK 堆栈创建一个 CloudFormation 堆栈。

当我初始化 CDK 应用时,创建了一个示例栈 HelloCdkStack ,你可以通过运行命令cdk ls来查看 CDK 栈的列表,如清单 3-9 所示。

(.venv) $ cdk ls
HelloCdkStack

Listing 3-9CDK Stack List

对于部署资源的 CDK,您必须用选择的编程语言定义这些资源。到目前为止,初始化的 CDK 应用没有做任何事情,因为没有定义任何资源。我将向您展示如何通过在以下步骤中创建 S3 时段来定义资源。

首先,清单 3-10 展示了如何从 AWS 构造库中安装亚马逊 S3 CDK 包。必须首先安装将要创建的每个 AWS 资源的 CDK 包。安装 CDK 不会安装资源级软件包;这些必须单独安装。

(.venv) $ pip install aws-cdk.aws-s3

Listing 3-10Installing Amazon S3 Package

安装完所有必需的包后,您可以开始在代码中定义资源及其属性。清单 3-11 显示了 CDK 堆栈中 S3 资源的定义。

  • 由于清单 3-7 中 CDK 应用被命名为 hello-cdk,定义堆栈的 Python 文件位置将是 hello_cdk/hello_cdk_stack.py
#hello_cdk/hello_cdk_stack.py

from aws_cdk import core as cdk
from aws_cdk import aws_s3 as s3

class HelloCdkStack(cdk.Stack):

    def __init__(self, scope: cdk.Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        bucket = s3.Bucket(self, "MyFirstBucket",
            versioned=True,)

Listing 3-11Amazon S3 CDK stack

在 CDK 定义资源后,应用就可以部署了。在部署之前,您可以合成并查看为定义的 CDK 资源生成的 CloudFormation 模板,如清单 3-12 所示。

(.venv) $ cdk synth
Resources:
  MyFirstBucketB8884501:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
    UpdateReplacePolicy: Retain
    DeletionPolicy: Retain
    Metadata:
      aws:cdk:path: HelloCdkStack/MyFirstBucket/Resource

Listing 3-12CDK synth output snippet

对于部署 CDK 应用,命令是cdk deploy。示例部署见清单 3-13 。

(.venv) $ cdk deploy
HelloCdkStack: deploying...
HelloCdkStack: creating CloudFormation changeset...

 ✅  HelloCdkStack

Stack ARN:
arn:aws:cloudformation:us-east-1:xxxxxxxxxxxx:stack/HelloCdkStack/36fb9a60-d6dc-11eb-8377-0ab7c9206afb

Listing 3-13CDK app deployment

当部署 CDK 应用时,它会创建一个 CloudFormation 堆栈,该堆栈也可以在 AWS 管理控制台上访问,如图 3-32 所示。

图 3-32

已部署的 CDK 应用的云结构堆栈

CDK CLI 也可用于删除已部署的资源。当 cdk 应用被删除时,底层的 CloudFormation 栈也被删除。清单 3-14 显示了在清单 3-13 中创建的单个 CDK 堆栈的删除。

(.venv) $ cdk destroy
Are you sure you want to delete: HelloCdkStack (y/n)? y
HelloCdkStack: destroying...

 ✅  HelloCdkStack: destroyed

Listing 3-14Deleting CDK app

监控和记录

监控是 DevOps 的重要组成部分。了解已部署应用的性能并记录应用活动,可以让您主动识别问题和模式,从而进一步提高软件质量。

让我们从 AWS CloudWatch 开始,探索可以帮助您满足应用中的日志记录和监控需求的 AWS 产品。

亚马逊云观测

Amazon CloudWatch 是用于监控和记录应用性能和活动的 AWS 产品。由于监控和日志记录有不同的组件,CloudWatch 根据功能分为不同的子服务。图 3-33 显示了 CloudWatch 控制台。左窗格中显示了 CloudWatch 的不同产品。

图 3-33

AWS 云观察服务控制台

让我们探讨一下 AWS CloudWatch 的一些常见用例。

云观察指标

大多数 AWS 服务原生地将指标数据发布到 CloudWatch 指标。当您创建一个与 CloudWatch 本机集成的 AWS 资源时,无需额外的操作,您就可以查看该资源的指标以监视该资源的不同方面。AWS 为每种资源类型提供了现成的指标支持;但是,您也可以发布自定义指标来监控 CloudWatch 本身不支持的组件。

可以在 AWS 控制台的图表中查看发布的指标,如图 3-34 所示。

图 3-34

可用的 CloudWatch 指标

CloudWatch 日志

这是 AWS CloudWatch 的日志聚合功能。存储在 AWS CloudWatch 中的日志可以来自运行在内部或云上的应用。一些 AWS 服务与 CloudWatch 日志进行了本机集成,并在那里存储它们的日志,几乎不需要额外配置。这种服务的例子是无服务器产品,如 AWS Lambda,这是一种允许您在云上执行代码而无需提供资源的服务,以及 AWS CodeBuild,它提供了一个编译代码、运行测试和产品工件的计算环境。

CloudWatch Logs 还有一个功能 CloudWatch Logs Insights,可以让您轻松查询和分析您的日志数据,以快速响应运营问题。

CloudWatch 警报

根据 CloudWatch 中的指标数据,您可以基于该数据创建警报,以便在达到特定阈值时执行操作。例如,您可以创建一个 CloudWatch 警报,以便在 CPU 利用率指标超过阈值时执行扩展操作。可以从 CloudWatch 日志数据事件中创建指标,因此这也提供了基于存储在 CloudWatch 日志中的应用日志中的事件来配置警报的能力。

AWS 云跟踪

您通过 AWS 控制台、CLI 或 SDK 工具在 AWS 上执行的所有活动都是由 AWS CloudTrail 监控和记录的 API 调用。CloudTrail 日志存储在亚马逊 S3 桶中。CloudTrail 存储的信息提供了 AWS 帐户中活动的审计跟踪,这使得审计用户的操作或代表用户执行操作的 AWS 服务变得更加容易。

摘要

在这一章中,我谈到了针对持续集成、持续交付、基础设施即代码和监控的不同 AWS DevOps 产品。我们探讨了基本细节、它们的用例,并在 AWS 管理控制台上演示了这些资源的示例供应。

在下一章,我们将详细介绍在 AWS 上配置 macOS 服务器,这将为在 AWS 上本地开发 iOS 提供基础。

四、AWS 上的 macOS 服务器

传统上,iOS 应用开发人员必须购买硬件 macOS 工作站或服务器来开发 iOS 应用,因为这些应用只能在 iOS 操作系统上构建、测试和部署。这限制了开发人员将云原生解决方案集成到他们的开发过程中的能力,从而无法利用云的力量。

Amazon EC2 Mac 实例消除了这些限制,在这一章中,我们将深入研究部署它的不同选项,开始使用它来开发您的 iOS 应用。

Amazon EC2 Mac 服务器

Amazon EC2 Mac 释放了在云上运行按需 macOS 工作负载的能力,因此允许 iOS 开发人员受益于 AWS 云提供的灵活性、可扩展性、敏捷性和成本优势。

它由 Mac mini 硬件提供支持,目前由 3.2 GHz 英特尔第八代(咖啡湖)酷睿 i7 处理器提供支持。您可以使用 EC2 Mac 实例为 Apple 设备(如 iPhone、iPad、iPod、Mac、Apple Watch 和 Apple TV)开发、构建、测试和签署应用。

要连接到 EC2 Mac 实例,您可以使用 SSH 进行命令终端访问,或者使用支持虚拟网络计算(VNC)协议的客户端来获得完整的用户界面(UI)体验。

EC2 限额和定价

因为每个 EC2 Mac 实例都是由实际的 Mac mini 硬件在幕后驱动的,所以默认情况下,AWS 会对提供 Mac 实例的帐户进行限制。这是为了防止滥用并为真实用户保留容量。

在您尝试部署之前,请查看您的 EC2 限额,以确保您有配额为您打算使用的区域中的帐户进行部署。要检查您的配额,请从 AWS 管理控制台转到 EC2 服务,如图 4-1 所示。

图 4-1

从 AWS 管理控制台访问 EC2

从 EC2 控制台,到达如图 4-2 所示的极限。

图 4-2

从 EC2 控制台访问限制页面

在那里可以搜索 Mac 专用主机限制,如图 4-3 所示。该限制表示您可以供应多少 Mac EC2 实例。如果适用,您可以从门户网站提出限额增加请求,并提供您的使用案例。

图 4-3

客户和地区的 EC2 Mac 限额

Mac 实例只能作为专用主机上的裸机实例,因为 Amazon EC2 Mac 实例和 Mac mini 服务器之间存在一对一的映射。您可以为每个专用主机启动一个 Mac 实例,并且可以与 AWS 组织内的 AWS 帐户或组织单位或整个 AWS 组织共享该专用主机。

EC2 Mac 实例不符合免费层的条件,按分配的专用主机计费,而不是按实例计费,专用主机在您可以释放之前有 24 小时的最短分配期。

部署 Amazon EC2 Mac 服务器

像大多数 AWS 服务一样,您可以使用各种选项来提供 EC2 Mac 实例。在这一节中,我将通过创建和提供示例代码向您展示可用的主要选项。

使用 AWS 管理控制台部署

AWS 管理控制台是开始提供 AWS 服务的最简单方法。要配置 EC2 Mac 服务器,首先要配置一台专用主机。参见图 4-4 了解如何从 EC2 控制台访问专用主机。

图 4-4

从 EC2 控制台访问专用主机

在专用主机控制台上,选择选项开始分配,如图 4-5 所示。

图 4-5

开始分配专用主机

如图 4-6 所示填写分配参数,分配专用主机。主要参数字段描述如下:

图 4-6

专用主机设置

  • 名称标签–为专用主机提供一个名称。

  • 实例系列–指定专用主机支持的实例系列。在这里,从下拉列表中选择实例族“MAC 1”

  • 支持多种实例类型–如果启用对多种实例类型的支持,主机可以支持所选实例系列中的不同实例类型。

    默认情况下,对于 Mac 实例族,此选项将灰显,因为当前只有一种实例类型。

  • 实例类型–主机支持的实例类型。如果不将主机配置为支持多种实例类型,则必须选择要支持的特定实例类型。在这里,你选择 mac1.metal

  • 可用区–分配主机的可用区;您可以选择列出的任何可用性区域,具体取决于您选择的数据中心。

  • 实例自动放置–启用自动放置以允许主机接受与其主机配置相匹配的无目标实例启动。禁用自动放置以允许主机仅接受目标实例启动。默认情况下,它不会被启用。

  • 主机恢复–主机恢复使用主机级运行状况检查来评估主机的可用性并检测底层系统故障。如果在主机上检测到故障,主机恢复会自动将故障主机上正在运行的实例重新启动到新的替代主机上。默认情况下,它不会被启用,并且不支持实例类型 mac1.metal。

  • 数量–您希望为此配置购买的专用主机数量。

    您在此选择的数量不能大于您的配额限制。

  • 一些可用性区域可能没有能力供应专用主机,这将导致分配失败;通过选择不同的可用性区域,再次尝试分配。

在分配之后,它可以立即在其上启动一个实例。图 4-7 显示了如何在专用主机上启动 EC2 Mac 实例的供应。

图 4-7

在专用主机上启动 Mac 实例

此操作将启动 EC2 实例创建过程。如图 4-8 所示,您选择 macOS Amazon 机器映像(AMI)用于启动 Mac EC2 实例。

图 4-8

为实例启动选择 macOS Amazon 机器映像(AMI)

下一步是选择实例类型。非灰色选项是所选 AMI 的可用实例类型。在图 4-9 中,已经选择了 mac1.metal 实例类型。

图 4-9

选择 macOS 实例类型

实例细节可以如图 4-10 所示进行配置。在这里,您可以配置 VPC、子网、主机配置等。

图 4-10

配置 EC2 Mac 详细信息

  • 此次启动不需要 IAM(身份访问管理)角色,因此为 IAM 角色选项选择“无”并继续。

对于实例存储,现在可以配置默认存储,如图 4-11 所示。默认存储足以进行初始部署和连接。

图 4-11

默认 Mac 实例存储

为了在启动后允许入站网络连接到 Mac 实例,定义了安全组规则,以允许从特定 IP 连接到适用的端口。如图 4-12 所示,允许从我的 IP 地址到 TCP 端口 22(安全外壳(SSH)协议端口)和 TCP 端口 5900(虚拟网络计算(VNC)协议端口)的连接。

图 4-12

为入站连接配置安全组规则

配置安全组规则后,检查输入的所有配置详细信息的准确性,并继续启动实例。

此外,对于到 Mac 实例的入站用户 SSH 连接,需要 EC2 密钥对。您可以使用您在帐户中创建的现有密钥对,也可以创建一个新的密钥对。图 4-13 显示了在启动实例之前创建新密钥对的过程。

图 4-13

在启动实例之前创建新的 EC2 密钥对

实例一旦启动,就会出现在专用主机下的运行实例选项卡下,如图 4-14 所示。

图 4-14

运行实例的专用主机

您还可以通过选择实例来查看有关运行实例的更多详细信息。这会将您重定向到 EC2 实例控制台,如图 4-15 所示。

图 4-15

Mac EC2 实例详细信息

使用 AWS CLI 部署

EC2 Mac 实例也可以从 AWS 命令行界面(CLI)提供。要使用 AWS CLI,必须先将其安装在工作站上,并使用适当的身份访问管理(IAM)凭据配置工作站。

要提供 EC2 Mac 实例,首先要分配一个专用主机,如清单 4-1 所示。

aws ec2 allocate-hosts --region us-east-1 --instance-type mac1.metal --availability-zone us-east-1c --auto-placement "on" --quantity 1

Listing 4-1Allocating dedicated host

一旦分配了专用主机,就可以创建一个 Mac 实例,如清单 4-2 所示。您将获得一个包含实例 ID 的响应,该实例 ID 可用于后续的 CLI 命令。

aws ec2 run-instances --region us-east-1 --instance-type mac1.metal --placement Tenancy=host --image-id ami-059ff882c04ebed21 --key-name my-key-pair

Listing 4-2Provisioning EC2 Mac instance on the dedicated host

通过描述清单 4-3 中所示的状态来验证创建的实例。使用在创建过程中从 CLI 响应中检索到的实例 ID。

aws ec2 describe-instance-status --instance-ids <Instance ID>

Listing 4-3Verifying Instance creation status

使用 AWS CloudFormation 部署

AWS CloudFormation 是一个基础设施即代码服务,它允许您对要在 jSON 或 YAML 模板中部署的资源进行建模。然后,该模板被传递给 AWS CloudFormation,以提供定义的资源。

要使用 CloudFormation 部署 EC2 Mac 实例,您将定义模板中所需的所有组件,如清单 4-4 所示。

Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: VPC to launch the EC2 Mac Instance
  SubnetId:
    Type: AWS::EC2::Subnet::Id
    Description: |
      Subnet to launch the EC2 Mac Instance............
  MacEc2Host:
    Type: String
    Default: h-xxxxxxxxxxxxxx
    Description: The Host ID of the Allocated.........
  SourceIp:
    Type: String
    Default: 1.2.3.4/32

    Description: |
      Source IP address and subnet mask...............
  Ec2KeyPairName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: Already existing EC2 keypair............
  MacOSAmi:
    Type: AWS::EC2::Image::Id
    Default: ami-059ff882c04ebed21
    Description:latest AMI ID for the Mac OS instance
Resources:
  Ec2MacSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      VpcId: !Ref VpcId
      GroupDescription: Enable SSH and VNC access.........
      SecurityGroupIngress:
      - CidrIp: !Ref SourceIp
        FromPort: 22
        IpProtocol: tcp
        ToPort: 22
      - CidrIp: !Ref SourceIp
        FromPort: 5900
        IpProtocol: tcp
        ToPort: 5900
  MacEc2Instance:
    Type: AWS::EC2::Instance
    Properties:
      Affinity: host
      ImageId: !Ref MacOSAmi
      KeyName: !Ref Ec2KeyPairName
      InstanceType: mac1.metal
      HostId: !Ref MacEc2Host
      SubnetId: !Ref SubnetId
      SecurityGroupIds:
        - !Ref Ec2MacSecurityGroup
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeType: gp2
            VolumeSize: '200'
            DeleteOnTermination: 'true'

Listing 4-4AWS CloudFormation template for EC2 Mac

模板的参数部分包含用户将提供的输入运行时参数,这些参数将在资源部分用于资源创建。

如清单 4-4 所示,模板中定义的两个资源是 EC2 Mac 安全组和 Mac 实例。要启动 CloudFormation 模板,从 AWS CloudFormation 控制台创建一个栈,选择文件,点击 next,如图 4-16 所示。

图 4-16

选择 EC2 Mac Cloudformation 模板以创建堆栈

接下来,您将输入模板中定义的用户参数,如图 4-17 所示。有些示例值已经作为默认值输入,应该用特定于您的环境和 AWS 帐户的信息覆盖这些值。

图 4-17

输入云形成堆栈参数

要在创建之前检查将要创建的资源,您可以创建一个变更集。改变设置如图 4-18 所示。

图 4-18

EC2 Mac 创建的云信息更改集

使用 Terraform 部署

Terraform 是一个开源基础设施,作为编码软件工具,允许您对模板中要提供的资源进行建模。Terraform 由 HashiCorp 创建,它使用一种称为 HashiCorp 配置语言(HCL)的声明式配置语言,文件扩展名为. tf。它还支持在 JSON 中声明资源。

清单 4-5 显示了 terraform HCL 模板中 EC2 Mac 资源的定义。

provider "aws" {
    region = "us-east-1"
}

variable "awsprops" {
    type = map(string)
    default = {
        vpcid = "vpc-937e84ee"
        subnetid = "subnet-c10c6fcf"
        ami = "ami-059ff882c04ebed21"
        keyname = "my-key-pair"
        hostid = "h-xxxxxxxxxxxx"
        sourceip = "1.2.3.4/32"
    }
}

resource "aws_security_group" "ec2-mac-instance-sg" {

  description = "Enable SSH and VNC access to Mac Instance"
  vpc_id = lookup(var.awsprops, "vpcid")

  // To Allow SSH Transport
  ingress {
    from_port = 22
    protocol = "tcp"
    to_port = 22
    cidr_blocks = [lookup(var.awsprops, "sourceip")]
  }

  // To Allow Port VNC Transport
  ingress {
    from_port = 5900
    protocol = "tcp"
    to_port = 5900
    cidr_blocks = [lookup(var.awsprops, "sourceip")]
  }
}

resource "aws_instance" "ec2-mac-instance" {
  ami = lookup(var.awsprops, "ami")
  key_name = lookup(var.awsprops, "keyname")
  host_id = lookup(var.awsprops, "hostid")
  instance_type = "mac1.metal"
  subnet_id = lookup(var.awsprops, "subnetid")
  vpc_security_group_ids = [
      aws_security_group.ec2-mac-instance-sg.id
  ]
  root_block_device {
    delete_on_termination = true
    volume_type = "gp2"
    volume_size = "200"
  }
}

Listing 4-5Terraform definition for EC2 Mac resources

与 AWS CloudFormation 一样,terraform 模板包含需要定制的输入变量和定义 EC2 安全性和 EC2 Mac 实例资源的资源部分。

要使用 Terraform,必须在工作站上安装软件,并且必须配置目标 AWS 帐户的身份访问管理(IAM)凭据。

部署 Terraform 中定义的资源。tf 文件,初始化您的工作目录,如清单 4-6 所示,使其成为 Terraform 工作目录,并安装所有的依赖项。

terraform> terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v3.49.0...
- Installed hashicorp/aws v3.49.0 (signed by HashiCorp)

Listing 4-6Initializing Terraform

在尝试部署以修复任何语法问题之前,您还可以验证您的 Terraform 文件,如清单 4-7 所示。

terraform> terraform validate
Success! The configuration is valid.

Listing 4-7Validating Terraform files in directory

要预览像 CloudFormation 变更集一样将被提供的所有资源,您可以执行一个terraform plan命令。这向您显示了有关要调配的资源及其关系的详细信息。清单 4-8 显示了这个命令的输出片段。

terraform> terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  + create

Terraform will perform the following actions:

  # aws_instance.ec2-mac-instance will be created
  + resource "aws_instance" "ec2-mac-instance" {
      + ami                           = "ami-059ff882c04ebed21"
      + arn                           = (known after apply)
      + associate_public_ip_address   = (known after apply)
.
.
.
.
Plan: 2 to add, 0 to change, 0 to destroy.

-----------------------------------------------------------------------------------------------
Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

Listing 4-8Viewing Terrform plan before resource creation

在查看了所有要创建的资源之后,要开始创建,您需要应用清单 4-9 中所示的配置。

terraform> terraform apply

Listing 4-9Applying terraform configuration

现在我已经展示了如何部署 EC2 Mac 服务器,接下来我们将探索如何连接到它。

连接到 Amazon EC2 Mac 服务器

对于每个新的 EC2 Mac 服务器,默认情况下禁用密码验证。第一次的默认访问方法是使用 SSHec2 用户帐户被配置用于 SSH 远程登录。要使用 SSH 进行连接,实例必须已经使用密钥对启动,并且其安全组允许从 SSH 连接发起的工作站进行 SSH 访问。

使用 SSH 连接后,可以配置密码验证,以允许使用虚拟网络计算(VNC)客户端进行连接。

使用 SSH 连接

为了使用 SSH 进行连接,本节讨论了各种选项,以适应您的操作系统和/或偏好。

Linux 或 Windows 上的命令终端

在 Windows 和 Linux 操作系统上,最常见的连接方法是通过命令终端并使用内置的 SSH 客户端。清单 4-10 中的示例显示了使用命令终端的 SSH 命令。

  • 如果你得到一个关于你的钥匙太开放和无保护的错误,用chmod 400 /path/my-key-pair.pem改变钥匙的许可。
ssh -i /path/my-key-pair.pem ec2-user@ec2-12-23-45-67.compute-1.amazonaws.com

Listing 4-10SSH on command terminal

窗户油灰

Putty 是一个用于 windows 的免费开源 telnet 和 SSH 客户端,也可用于连接 EC2 Mac 实例。要使用 Putty,您必须将。pem 密钥对与. ppk 密钥的兼容性。转换后,您提供。ppk 键如图 4-19 所示。

图 4-19

为 Putty 会话提供身份验证

配置好身份验证后,按照格式 ec2-user@ <主机名> 指定主机名以及端口和连接类型,如图 4-20 所示。

图 4-20

正在启动 Putty SSH 会话

点击打开,就登录到 EC2 Mac 服务器的命令终端,如图 4-21 所示。

图 4-21

EC2 Mac 服务器的命令终端

正在连接 VNC 客户端

要连接到 Mac 服务器的用户界面(UI ),您必须使用 VNC 客户端。但是在使用 VNC 客户端之前,有几个先决条件需要配置。

设置登录密码

默认情况下,ec2 用户禁用密码验证。要使用 VNC 客户端并连接到 UI,必须为 ec2 用户创建密码,如清单 4-11 所示。

ec2-user@ip-172-31-47-239 ~ % sudo passwd ec2-user
Changing password for ec2-user.
New password:
Retype new password:

################################### WARNING ###################################
# This tool does not update the login keychain password.                      #
# To update it, run `security set-keychain-password` as the user in question, #
# or as root providing a path to such user's login keychain.                  #
###############################################################################

Listing 4-11Setting up password for default ec2-user account

请保管好您在此设置的密码,因为它将用于使用 VNC 客户端登录到您的服务器。

设置苹果远程桌面

要在 Mac 服务器上启用远程桌面连接,必须从 Mac 服务器的终端启动苹果远程桌面代理,如清单 4-12 所示。

ec2-user@ip-172-31-47-239 ~ % sudo /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Resources/kickstart \
-activate -configure -access -on \
-restart -agent -privs -all
Starting...
Warning: macos 10.14 and later only allows control if Screen Sharing is enabled through System Preferences.
Activated Remote Management.
Stopped ARD Agent.
ec2-user: Set user remote control privileges.
ec2-user: Set user remote access.
Done.

Listing 4-12Starting Apple Remote Desktop Agent

设置 SSH 端口转发

您可以从工作站上的 VNC 客户端直接连接到端口 5900 (VNC 端口)上的 Mac 服务器的 IP 地址,但是 VNC 协议被认为是不安全的。一种更安全的方法是从您的工作站使用 SSH 端口转发功能通过 SSH 隧道传输 VNC 流量。

清单 4-13 展示了如何将本地主机端口 5900 的所有流量转发到 EC2 Mac 服务器端口 5900。因此,要连接到 Mac 服务器,您需要向本地主机端口 5900 发送流量。

ssh -L 5900:localhost:5900 -i /path/my-key-pair.pem ec2-user@your-instance-public-dns-name

Listing 4-13SSH tunneling VNC traffic

下载 VNC 客户端并连接

根据您的操作系统,有多种 VNC 客户端选项可供使用。一个这样的选项是 VNC 浏览器,它可以跨多个操作系统使用;可以下载,如图 4-22 所示。

图 4-22

下载 VNC 客户端

它可以安装在 Windows 操作系统上,如图 4-23 所示。

图 4-23

在 Windows 上安装 VNC 客户端

安装完成后,确保按照清单 4-13 中的描述设置了端口 5900 SSH 隧道,然后可以通过连接到本地主机开始连接 Mac 服务器,如图 4-24 所示。

图 4-24

使用 VNC 客户端连接到 EC2 Mac 服务器

连接成功后,您会看到 EC2 Mac 服务器的登录提示,如图 4-25 所示。

图 4-25

EC2 Mac 服务器的登录提示

在清单 4-11 中,我向您展示了如何为默认 ec2 用户设置密码。您在那里设置的密码是 ec2 用户将用来登录的。

认证成功后,您将登录,如图 4-26 所示。

图 4-26

EC2 Mac 服务器主屏幕

使用 Amazon CloudWatch 监控 EC2 Mac 服务器

默认情况下,EC2 Mac 实例会向 Amazon CloudWatch 发出指标以进行性能监控。它发送 CPU 利用率、网络使用信息等指标。EC2 Mac 实例的指标可以在 EC2 控制台上查看,方法是在实例上选择,然后转到 Monitoring 选项卡。这方面的一个例子如图 4-27 所示。

图 4-27

EC2 控制台上的实例度量信息

这些指标也可以在亚马逊 CloudWatch 控制台上查看。CloudWatch 控制台为您提供了更多的图表选项,并允许您在同一个图表上比较多个指标,如图 4-28 所示。

图 4-28

Cloudwatch 上的实例度量图

要禁用向 CloudWatch 发送 CPU 利用率等系统监控指标的代理,可以运行清单 4-14 中所示的设置。

$ sudo setup-ec2monitoring [enable | disable]

Listing 4-14Configuring EC2 system monitoring for Mac instance

清理 Amazon EC2 Mac 服务器

如果不经常使用 Amazon EC2 服务器,要清理它,首先要终止 EC2 实例,然后释放专用主机。

要终止实例,从 EC2 仪表板中,选择实例并选择您想要终止的 mac1.metal 实例。选择实例状态,然后选择终止实例

由于 Amazon EC2 Mac 实例不是按实例收费的,而是由专用主机收费的,终止实例并不能停止收费,必须释放专用主机才能停止收费。

  • 在分配主机 24 小时后,才能释放专用主机。

要释放主机,从 EC2 仪表板中,选择专用主机并选择您想要释放的专用主机。选择动作,然后选择发布主机

摘要

我们讨论了部署 EC2 macOS 实例的细节,探索了不同的部署方法。我还向您展示了不同的连接选项,同时还介绍了连接 EC2 Mac 服务器的先决条件。

在下一章中,我们将在此基础上进行构建,我将向您展示如何在 EC2 macOS 实例上安装和设置各种 iOS 开发和构建工具。

五、在 macOS 实例上设置开发工具

要在 Amazon EC2 Mac 实例上开始开发,就像任何其他 Mac 构建服务器一样,必须安装 Xcode 等 iOS 构建工具。还有其他开源和第三方自动化工具,如 Jenkins,Fastlane 等。,它与 Xcode 集成以增加自动化并改进 iOS 开发流程。

在本章中,我们将探讨如何在亚马逊 EC2 macOS 实例上安装 Xcode、Jenkins、Fastlane 和 GitLab Runner。但是,在安装软件之前,必须有足够的存储空间,因此我们将从如何增加 macOS 实例的卷大小开始。

增加 macOS 实例宗卷大小

要安装像 Xcode 这样的 iOS 应用构建工具,必须有足够的磁盘空间。macOS 实例卷大小可以在启动时或 Mac 实例运行后修改。如果在启动时没有修改卷大小,Amazon EC2 Mac 实例提供的默认磁盘大小可能不够。

macOS 实例使用 Amazon 弹性块存储(EBS)卷。增加正在运行的 macOS 实例的存储容量包括增加所连接的 EBS 卷的容量、重新启动实例,以及使增加的磁盘空间可供使用。

在 EC2 控制台上选择 macOS 实例,可以看到实例卷大小,如图 5-1 所示。要增加卷大小,点击 EBS 卷 ID,如图 5-1 所示;这将引导您进入 EBS 控制台。

图 5-1

macOS 实例详细信息中显示的卷大小

进入卷修改页面,如图 5-2 所示。

图 5-2

选择修改卷选项

修改实例 EBS 卷大小。图 5-3 中所示的示例将卷增加到 200 GB。

图 5-3

将音量调整到所需的大小

调整正在运行的 macOS 实例的附加 EBS 卷的大小后,在重新启动之前,该卷在实例中不可见。您可以从 EC2 控制台重启 macOS 实例,如图 5-4 和 5-5 所示。

图 5-5

确认实例重新启动

图 5-4

调整宗卷大小后重新启动 macOS 实例

在调整 EBS 卷大小时,macOS 重新启动后,新的磁盘大小应该在 macOS 实例上可见,如清单 5-1 所示。

ec2-user@ip-172-31-47-239 ~ % diskutil list external physical
/dev/disk1 (external, physical):
   #:           TYPE NAME            SIZE       IDENTIFIER
   0:      GUID_partition_scheme   *214.7 GB      disk1
   1:            EFI EFI            209.7 MB      disk1s1
   2:   Apple_APFS Container disk2   64.2 GB      disk1s2

Listing 5-1Listing disk size

如清单 5-1 所示,新的磁盘大小是可见的,但是 APFS 容器的大小仍然较小,因此增加的磁盘空间还没有被使用。增加的磁盘大小可以变得可用,如清单 5-2 所示。

ec2-user@ip-172-31-47-239 ~ % PDISK=$(diskutil list physical external | head -n1 | cut -d" " -f1)

ec2-user@ip-172-31-47-239 ~ % APFSCONT=$(diskutil list physical external | grep "Apple_APFS" | tr -s " " | cut -d" " -f8)

ec2-user@ip-172-31-47-239 ~ % yes | sudo diskutil repairDisk $PDISK
Repairing the partition map might erase disk1s1, proceed? (y/N) Started partition map repair on disk1
Checking prerequisites

Listing 5-2Repairing disk and making increased size usable

修复之后,最后一步是调整苹果 APFS 容器的大小,如清单 5-3 所示。

ec2-user@ip-172-31-47-239 ~ % sudo diskutil apfs resizeContainer $APFSCONT 0

Started APFS operation
Aligning grow delta to 150,323,855,360 bytes and targeting a new physical store size of 214,538,608,640 bytes
Determined the maximum size for the targeted physical store of this APFS Container to be 214,537,580,544 bytes

Listing 5-3Resizing APFS container size

设置 Xcode

Xcode 可以从 App Store 手动安装在 macOS 实例上,正如第一章所讨论的。安装 Xcode 后,要开始使用 Xcode,您必须接受 Xcode 和 iOS SDK 许可协议,如图 5-6 所示。

图 5-6

Xcode 和 iOS SDK 许可协议

如果提示输入密码以授予 Xcode 权限,请输入您的用户密码。如果使用默认的 ec2 用户,这是为用户创建的用户密码,如第四章所述。

一旦 Xcode 准备好使用,它应该会进入它的欢迎页面,如图 5-7 所示。

图 5-7

Xcode 欢迎页面

Xcode 命令行工具

从 App Store 安装 Xcode 时,它的命令行工具也会被安装,无需任何进一步操作。可以从命令终端验证安装,如清单 5-4 所示。

ec2-user@ip-172-31-47-239 ~ % xcode-select --install

xcode-select: error: command line tools are already installed, use "Software Update" to install updates

ec2-user@ip-172-31-47-239 ~ % xcodebuild
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild

User defaults from command line:
    IDEPackageSupportUseBuiltinSCM = YES

xcodebuild: error: The directory /Users/ec2-user does not contain an Xcode project

.

ec2-user@ip-172-31-47-239 ~ % xcodebuild -version
Xcode 12.5.1
Build version 12E507

Listing 5-4Verifying Xcode command line tools installation

陷害 Jenkins

Jenkins 是一个开源的自动化和应用构建工具。它与各种其他工具相集成,这使得它适用于各种类型的构建和自动化。Jenkins 支持分布式构建;通过使用并行运行作业的代理,可以为每个生成项目使用不同的生成环境。

这些代理由控制器控制,控制器是配置和调度所有构建作业的主要 Jenkins 节点。代理可以是与控制器相同类型的环境,在控制器中调度作业以平衡工作负载,也可以是与主控制器不同的环境,在主控制器中,基于正在构建的应用所需的构建环境在代理上调度作业。

让我们在接下来的两节中探索如何在 Amazon EC2 实例上的 Linux 环境中配置 Jenkins 控制器,以及如何使用 macOS 构建代理来构建 iOS 应用。

供应 Jenkins 控制器

控制器将在 Amazon EC2 Linux 实例上提供,因此,首先,必须从 EC2 控制台创建一个 EC2 实例,如图 5-8 所示。

图 5-8

从 EC2 控制台启动 Amazon EC2 实例

选择适用 AWS 地区的最新 Amazon Linux Amazon Machine Image(AMI),如图 5-9 所示。

图 5-9

选择最新的亚马逊 Linux AMI

选择实例类型,并根据需要配置实例和存储容量。对于安全组,需要 SSH (TCP 端口 22)访问来启用对 Jenkins 服务器的访问。Jenkins 还在 TCP 端口 8080 上提供流量,因此这必须在安全组中得到允许。安全组配置示例如图 5-10 所示。这些规则可以通过工作站的源 IP 地址进一步限制。

图 5-10

配置安全组规则

在实例启动之后,下一步是通过 SSH 登录实例,安装 Jenkins 软件。

因为提供了 Amazon Linux EC2 实例,所以将使用 yum package manager 来安装 Jenkins。类似地,其他操作系统中的包管理器可以用来在那些操作系统上安装 Jenkins。

首先,执行实例上所有包的快速软件更新,如清单 5-5 所示。

[ec2-user ~]$ sudo yum update

Listing 5-5Updating software packages

更新软件包后,可以将 Jenkins repo 添加到 yum 中,如清单 5-6 所示。

[ec2-user ~]$ sudo wget -O /etc/yum.repos.d/jenkins.repo \
    https://pkg.jenkins.io/redhat-stable/jenkins.repo

Listing 5-6Adding Jenkins to yum repo

接下来是导入 RPM 的密钥文件来验证包。这显示在清单 5-7 中。

[ec2-user ~]$ sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key

[ec2-user ~]$ sudo yum upgrade

Listing 5-7Import rpm key file to verify package

然后可以安装 Jenkins,如清单 5-8 所示。

[ec2-user ~]$ sudo yum install jenkins java-1.8.0-openjdk-devel -y

[ec2-user ~]$ sudo systemctl daemon-reload

Listing 5-8Installing Jenkins

安装后,Jenkins 可以作为服务启动,如清单 5-9 所示。

[ec2-user ~]$ sudo systemctl start jenkins

Listing 5-9Starting Jenkins as a service

如清单 5-10 所示,可以检查 Jenkins 状态。

[ec2-user ~]$ sudo systemctl status jenkins

Listing 5-10Checking Jenkins status

最初设置 Jenkins 时,需要一个初始管理员密码。如清单 5-11 所示,可以检索该密码。

[ec2-user ~]$ sudo cat /var/lib/jenkins/secrets/initialAdminPassword

Listing 5-11Retriving initial Admin Password

要通过管理界面首次访问您的 Jenkins 服务器,请从您的网络浏览器连接到http://<your_server_public_DNS>:8080。初始设置页面如图 5-11 所示。输入取回的初始密码,如清单 5-11 所示。

图 5-11

Jenkins 初始设置页面

为了支持不同类型的应用和工具,Jenkins 使用插件来扩展其功能。在 Jenkins 初始设置期间,您可以选择安装特定的插件,或者安装建议的插件,如图 5-12 所示。

图 5-12

安装 Jenkins 插件

还必须创建一个初始的管理员用户来验证 Jenkins。初始管理员用户的设置如图 5-13 所示。

图 5-13

创建初始管理员用户

在安装了所有插件并设置了初始管理员用户之后,Jenkins 就可以开始创建作业和注册构建代理了。全新的 Jenkins 安装欢迎页面如图 5-14 所示。

图 5-14

Jenkins 欢迎页面

EC2 Mac 实例作为 Jenkins 构建代理

创建 Jenkins 控制器后,您可以为分布式生成设置生成代理。要构建 iOS 应用,必须存在 macOS 构建代理。让我们探索如何通过 SSH 将 EC2 Mac 实例作为构建代理添加到 Jenkins 控制器中。

要添加 Jenkins 构建代理,必须安装 Java。清单 5-12 展示了如何在 EC2 Mac 上安装带有 Homebrew 的 Java 开发工具包。

ec2-user@ip-172-31-47-239 ~ % su ec2-user -c '/usr/local/bin/brew install openjdk@8'
Password:
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> Updated Formulae

Updated 20 formulae.

==> Downloading https://ghcr.io/v2/homebrew/core/libpng/manifests/1.6.37
######################################################################## 100.0%
.
.
.
.
.
==> Installing dependencies for openjdk@8: libpng and freetype
==> Installing openjdk@8 dependency: libpng

Listing 5-12Installing OpenJDK on EC2 Mac

在用 Homebrew 安装 OpenJDK 之后,为它创建一个符号链接并验证安装,如清单 5-13 所示。

sh-3.2# ln -sfn /usr/local/opt/openjdk@8/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-8.jdk

sh-3.2# java -version

openjdk version "1.8.0_282"
OpenJDK Runtime Environment (build 1.8.0_282-bre_2021_01_20_16_06-b00)
OpenJDK 64-Bit Server VM (build 25.282-b00, mixed mode)

Listing 5-13Create symlink for OpenJDK and verify Installation

安装 Java 之后,下一个需求是创建一个 Jenkins 用户并为该用户设置 SSH 访问。Jenkins 控制器将使用该用户通过 SSH 连接到 macOS 构建代理,以提交构建作业。您可以创建一个新的 Jenkins 用户,如清单 5-14 所示。

sh-3.2# sysadminctl -addUser jenkins
2021-07-10 19:50:42.793 sysadminctl[6437:155160] --------------
2021-07-10 19:50:42.793 sysadminctl[6437:155160] No clear text password or interactive option was specified (adduser, change/reset password will not allow user to use FDE) !
2021-07-10 19:50:42.793 sysadminctl[6437:155160] --------------
2021-07-10 19:50:42.970 sysadminctl[6437:155160] Creating user record...
2021-07-10 19:50:43.043 sysadminctl[6437:155160] Assigning UID: 503 GID: 20
2021-07-10 19:50:43.076 sysadminctl[6437:155160] Creating home directory at /Users/jenkins

Listing 5-14Creating Jenkins user

创建用户后,您可以设置一个新的密钥,或者在 macOS 实例上重用现有的默认 ec2-user 密钥。清单 5-15 展示了如何对新的 Jenkins 用户重用默认的 ec2 用户 SSH 凭证。

sh-3.2# mkdir /Users/jenkins/.ssh/

sh-3.2# cp -a /Users/ec2-user/.ssh/. /Users/jenkins/.ssh/

sh-3.2# cp /Users/ec2-user/.ssh/* /Users/jenkins/.ssh/.

sh-3.2# chown -R jenkins /Users/jenkins/.ssh

sh-3.2# chmod 700 /Users/jenkins/.ssh

sh-3.2# chmod 600 /Users/jenkins/.ssh/authorized_keys

Listing 5-15Setting up SSH keys for Jenkins user

接下来,让我们确保 Jenkins 控制器可以通过 SSH 从安全组访问 EC2 Mac 实例。

如图 5-15 所示,为 Jenkins 控制器实例的/32 私有 IP 地址配置 TCP 端口 22 访问。使用私有 IP 地址是因为 Jenkins 控制器和 EC2 Mac 实例位于同一个虚拟私有云(VPC)中。如果它们在不同的 VPC 中,并且 Jenkins 控制器将通过互联网与 Mac 实例连接,您将添加 Jenkins 控制器的公共 IP 地址。

图 5-15

EC2 Mac 实例的安全组配置

安装了 Java、创建了 Jenkins 用户、设置了 SSH 访问并配置了安全组之后,就可以添加 EC2 macOS 实例作为构建节点了。

在 Jenkins 用户界面上,选择“管理 Jenkins”选项,然后选择“管理节点和云”,如图 5-16 所示。

图 5-16

管理 Jenkins 选项

启动添加新节点的流程,并为节点提供名称,如图 5-17 所示。

图 5-17

添加新的 Jenkins 节点

将配置节点的连接信息,包括节点的 IP 地址、启动方法、标签、节点的凭证等。该标签是在生成作业中配置的,控制器使用它来标识要在其上调度特定作业的生成代理。图 5-18 显示了使用 SSH 启动方法和 iOS 标签的节点配置示例。

SSH 凭证必须单独配置。凭据可以预先创建,也可以在添加节点时创建。图 5-18 显示了如何在配置构建节点时添加新凭证。

图 5-18

为 Jenkins 节点配置新凭据

要添加 SSH 凭证,您需要提供 Jenkins 用户名和 SSH 私有密钥。要获取私钥内容,请打开为 Jenkins 用户 SSH 访问配置的私钥文件。

  • 在本例中,与清单 5-15 中配置的相同的 SSH 私有密钥用于 ec2-user 和 Jenkins 用户,因此从您的工作站检索该私有密钥的内容。

图 5-19 显示了配置 SSH 凭证的示例。

图 5-19

在 Jenkins 中配置 SSH 凭证

可以为节点配置路径变量等环境变量,如图 5-20 所示。

图 5-20

为节点配置环境变量

保存新节点的配置。在图 5-18 中,主机密钥验证被配置为手动信任,因此在保存新节点配置后,Jenkins 控制器尝试通过 SSH 连接到构建代理,并且在 Jenkins 节点的左侧选项中显示提示,请求信任 Jenkins 控制器;选择此项以允许继续连接。

您可以在 Jenkins 上查看控制台输出,以查看状态并了解它的运行情况。列表 5-16 显示了一个成功添加代理的控制台输出示例。

[07/11/21 17:31:16] [SSH] Checking java version of java
[07/11/21 17:31:16] [SSH] java -version returned 1.8.0_282.
[07/11/21 17:31:16] [SSH] Starting sftp client.
[07/11/21 17:31:16] [SSH] Copying latest remoting.jar...
[07/11/21 17:31:16] [SSH] Copied 1,502,119 bytes.
Expanded the channel window size to 4MB
[07/11/21 17:31:16] [SSH] Starting agent process: cd "/Users/Jenkins" && java  -jar remoting.jar -workDir /Users/Jenkins -jar-cache /Users/Jenkins/remoting/jarCache
Jul 11, 2021 5:31:17 PM org.jenkinsci.remoting.engine.WorkDirManager initializeWorkDir
INFO: Using /Users/Jenkins/remoting as a remoting work directory
Jul 11, 2021 5:31:17 PM org.jenkinsci.remoting.engine.WorkDirManager setupLogging

INFO: Both error and output logs will be printed to /Users/Jenkins/remoting
<===[JENKINS REMOTING CAPACITY]===>channel started
Remoting version: 4.7
This is a Unix agent
Evacuated stdout
Agent successfully connected and online

Listing 5-16Output snippet of adding Jenkins agent

添加一个构建节点后,它会出现在节点列表中,如图 5-21 所示。

图 5-21

Jenkins 建立节点

建立 Fastlane

Fastlane 是一个开源自动化工具,用于自动化移动应用开发。它自动化了构建 iOS 应用的所有方面,从开发到发布到应用商店。其主要特点是

  • 在 App Store 中使用的自动化屏幕截图

  • 自动化测试版部署

  • 应用商店部署

  • 代码签名

Fastlane 可以与 Jenkins 集成,为 iOS 应用开发创建完整的端到端持续集成持续交付(CICD)流程。

Fastlane 可以使用自制软件简单地安装在 macOS 工作站上,如清单 5-17 所示。

ec2-user@ip-172-31-47-239 ~ % brew install fastlane
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> Updated Formulae
Updated 52 formulae.
==> Updated Casks

Updated 13 casks.
.
.
.
.
.
==> Installing fastlane
==> Pouring fastlane--2.187.0.big_sur.bottle.1.tar.gz

Listing 5-17Fastlane installation output snippet

安装后,您可以验证安装并开始使用 Fastlane。清单 5-18 中显示了启动 Fastlane 的示例和输出示例。

清单 5-18。从 Fastlane 出发

设置 GitLab

GitLab 是一个 DevOps 平台,它提供了许多特性来提高软件开发过程中的灵活性。其中的一些特性包括用于管理源代码的 git repository manager、持续集成以及用于自动构建和部署应用的部署管道等。

对于其持续集成和部署特性,它使用 GitLab runner。GitLab Runner 是一个与 GitLab CICD 协同工作的应用,用于在管道中运行作业。GitLab Runner 应用可以安装在单独的基础设施和操作系统上,这取决于 Runner 将要执行的工作。

GitLab Runner 也可以安装在 macOS 上运行 iOS 相关的作业,那么我们就来探讨一下如何设置 GitLab,在 macOS EC2 实例上安装一个 GitLab Runner。

创建 GitLab 项目

要开始使用 GitLab,您必须注册一个 GitLab 帐户。可以在 https://gitlab.com/ 上免费报名。然后,创建一个如图 5-22 所示的项目。

图 5-22

创建 GitLab 项目

接下来,您可以选择如何创建项目,如图 5-23 所示,您可以创建一个空白项目或使用一个模板,该模板会用文件预先填充您的项目。

图 5-23

选择项目初始配置

配置项目名称、URL 和可见性级别(私有或公共)。图 5-24 显示了一个示例项目配置。

图 5-24

配置和创建 GitLab 项目

设置 macOS GitLab Runner

当您创建 GitLab 项目时,会为项目创建一个存储库,您可以访问许多 DevOps 特性,其中包括 CICD。要设置可以构建 iOS 应用的 GitLab CICD 管道,必须设置一个 macOS GitLab 运行程序。

项目的 GitLab Runner 配置可以在项目设置中进入,如图 5-25 所示。

图 5-25

GitLab 项目 CICD 设置

要在 macOS 实例上注册 GitLab runner,需要 GitLab 位置的 URL 和唯一的注册令牌。在项目 CICD 设置中展开滑道即可找回两者,如图 5-26 所示。

图 5-26

GitLab Runner 注册令牌和 URL

GitLab Runner 以二进制形式提供。您可以下载二进制文件并在 macOS 实例上提供适当的权限,如清单 5-19 所示。

ec2-user@ip-172-31-47-239 ~ % sudo curl --output /usr/local/bin/gitlab-runner "https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64"

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 53.0M  100 53.0M    0     0  92.6M      0 --:--:-- --:--:-- --:--:-- 92.4M

ec2-user@ip-172-31-47-239 ~ % sudo chmod +x /usr/local/bin/gitlab-runner

Listing 5-19Download GitLab Runner binary for macOS

现在您可以注册跑步者,如清单 5-20 所示。注册是一个交互式操作,您需要提供注册令牌、GitLab URL、跑步者描述等。

ec2-user@ip-172-31-47-239 ~ % gitlab-runner register

Runtime platform                                    arch=amd64 os=darwin pid=4212 revision=c1edb478 version=14.0.1
WARNING: Running in user-mode.
WARNING: Use sudo for system-mode:
WARNING: $ sudo gitlab-runner...

Enter the GitLab instance URL (for example, https://gitlab.com/):
https://gitlab.com/
Enter the registration token:
nxxxxxxxxxxxxxxi
Enter a description for the runner:
[ip-172-31-47-239.ec2.internal]: mac os runner

Enter tags for the runner (comma-separated):

Registering runner... succeeded                     runner=nYR2beCG
Enter an executor: custom, docker, parallels, docker-ssh, shell, ssh, virtualbox, docker+machine, docker-ssh+machine, kubernetes:
shell
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Listing 5-20GitLab Runner registration

成功的转轮注册不会安装转轮,您必须单独安装转轮。清单 5-21 展示了如何安装和启动 GitLab Runner。

ec2-user@ip-172-31-47-239 ~ % gitlab-runner install

Runtime platform                                    arch=amd64 os=darwin pid=4237 revision=c1edb478 version=14.0.1

ec2-user@ip-172-31-47-239 ~ % gitlab-runner start

Runtime platform                                    arch=amd64 os=darwin pid=4240 revision=c1edb478 version=14.0.1

Listing 5-21Installing and starting GitLab Runner

一旦安装了 GitLab Runner,您就可以开始从 GitLab CICD 管道向这个 Runner 调度作业。要验证 runner 是否已注册到您的 GitLab 项目并准备好接收作业,请确保您可以在 GitLab 项目的 runner 列表中看到注册的 macOS runner。图 5-27 显示了在 GitLab 上注册为 runner 的 macOS 实例。

图 5-27

在 GitLab 上查看注册的 macOS runner

摘要

设置 iOS 应用开发环境需要安装不同的软件,如 iOS 专用的 Xcode 和其他第三方及开源工具。我们已经介绍了在 macOS Amazon EC2 实例上安装和设置所有这些工具,以便为开发做好准备。

六、使用 AWS CodeCommit 的源代码管理

正如第三章所讨论的,AWS CodeCommit 是一个托管的私有 Git 库。当交互和使用 CodeCommit 时,您使用标准的 Git 工具,所有标准的 Git 概念和特性都适用。

在本章中,我们将深入探讨如何使用 AWS CodeCommit 进行源代码管理,首先是如何连接到 CodeCommit 存储库以添加源代码,以及诸如拉请求、分支等功能是如何实现的。,工作。

在开始使用 AWS CodeCommit 之前,让我们回顾一下基本的 Git 基础知识。

Git 基础

Git 是一个开源的版本控制系统。它跟踪您对启用它的目录中的文件所做的更改,这允许您在任何时间点恢复到文件的任何版本。它还使协作变得容易,因为它允许将不同人对文件所做的更改合并到一个文件中。

Git 安装

所有主要平台的 Git 客户端都可以从 Git 网站下载,如图 6-1 所示。

图 6-1

Git 客户端下载

对于不同的操作系统,可以使用软件包管理器从命令行下载它。清单 6-1 分别展示了如何为 macOS 和 Debian/Ubuntu 系统安装 Git。

macOS
$ brew install git

Debian/Ubuntu

$ apt-get install git

Listing 6-1Git installation with package managers

初始化 Git 存储库

一旦安装了 Git,要在目录中启用 Git,必须对它进行初始化。在一个目录中初始化 Git 意味着您希望它启动版本控制并开始跟踪该目录中的所有更改。Git 可以在目录中初始化,如清单 6-2 所示。

$ git init
Initialized empty Git repository in /home/cloudshell-user/git-diretory/.git/
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Listing 6-2Initializing Git repository and checking Git status

记录对 Git 存储库的更改

如清单 6-2 所示,在 Git 初始化的目录中没有 Git 要跟踪的文件,因为它是一个空目录。新文件被添加到目录中,如清单 6-3 所示。

$ touch file1 file2 file3
$ git status
On branch master

No commits yet

Untracked files

:
  (use "git add <file>..." to include in what will be committed)
        file1
        file2
        file3

nothing added to commit but untracked files present (use "git add" to track)

Listing 6-3Adding new files and checking Git status

文件被添加到目录中,但不是为了 Git 开始跟踪而添加的。为了让 Git 开始跟踪这些新文件,首先应该如清单 6-4 所示进行修改。

$ git add .
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   file1
        new file:   file2
        new file:   file3

Listing 6-4Staging changes and checking Git status

在变更被暂存之后,Git 开始跟踪这些文件的最后一步是提交变更。如果这是你第一次使用 Git,你必须如清单 6-5 所示配置你的名字和邮箱。向 Git 提交文件时,必须提供注释来描述正在提交的更改;这提供了-m标志,如清单 6-5 所示。

$ git config --global user.name "Enter Your Name"
$ git config --global user.email "Enter Your Email"

$ git commit -m "Add files"
[master (root-commit) 6ebb411] Add files
 3 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 file1
 create mode 100644 file2
 create mode 100644 file3
$ git status
On branch master
nothing to commit, working tree clean

Listing 6-5Committing changes and checking Git status

克隆和使用远程 Git 存储库

有时,您已经有一个现有的项目存储在一个远程 Git 存储库中,如 GitHub、GitLab、AWS CodeCommit 等。,你想在本地工作。为此,您可以通过克隆来本地下载存储库。在本地克隆了存储库之后,您可以对文件进行更改,并通过前面描述的 Git 生命周期来开始跟踪您的更改。

清单 6-6 显示了一个克隆存储库的例子。在这里,我克隆了公共 AWS CLI GitHub 存储库。要克隆您拥有的私有存储库,系统会提示您进行身份验证。

$ git clone https://github.com/aws/aws-cli.git
Cloning into 'aws-cli'...
remote: Enumerating objects: 84578, done.
remote: Counting objects: 100% (790/790), done.
remote: Compressing objects: 100% (246/246), done.
remote: Total 84578 (delta 556), reused 763 (delta 543), pack-reused 83788
Receiving objects: 100% (84578/84578), 53.34 MiB | 20.19 MiB/s, done.
Resolving deltas: 100% (57974/57974), done.

Listing 6-6Cloning remote Git repository

在本地克隆远程存储库后,本地存储库会自动配置为指向远程存储库,以便将来进行同步操作。例如,如果远程存储库中有更新,本地存储库可以提取这些更改以与本地存储库合并,或者如果本地存储库中有更改,则需要推送这些更改以更新远程存储库。

清单 6-7 展示了如何查看为本地存储库配置的远程存储库,如何通过拉和推操作来保持本地和远程存储库同步,以及如何为本地存储库配置不同名称的其他远程存储库。Git 为远程存储库使用的默认简称是 origin,并且配置了一个新的远程存储库 origin2,如清单 6-7 所示。

$ cd aws-cli/
$ git remote -v
origin  https://github.com/aws/aws-cli.git (fetch)
origin  https://github.com/aws/aws-cli.git (push)

$ git pull origin

Already up to date.

$ git push origin master

$ git remote add origin2 https://github.com/aws/aws-cli.git
$ git remote -v
origin2 https://github.com/aws/aws-cli.git (fetch)
origin2 https://github.com/aws/aws-cli.git (push)
origin  https://github.com/aws/aws-cli.git (fetch)
origin  https://github.com/aws/aws-cli.git (push)

Listing 6-7Listing remote repositories and configuring a new remote repository

Git 分支

在 Git 中,分支是指向提交的指针。它用于分离正在进行的文件工作,并维护 Git 存储库的独立并发版本。如果一个文件存在于多个分支上,则在一个分支上对此文件所做的更改不会影响另一个分支中的同一文件。分支通常用于开发新特性,存储来自特定提交的项目的特定版本,等等。

在新的 Git 存储库中,当您创建第一个提交时,会为您创建一个默认分支。可以创建附加分支来跟踪项目的不同版本。

拉取请求

拉请求允许您和存储库中的其他用户从一个分支到另一个分支查看、添加注释和合并代码更改。Pull requests 是多个存储库用户协作的一种方式,在应用的新版本发布之前,通过检查代码更改和修复 bug 来实现。

一个典型的例子是,当您有一个主 Git 分支,其中包含您的应用的生产部署版本,而新功能是在单独的功能分支中开发的。当功能分支中的功能准备好进行生产部署时,拉请求允许团队成员在将功能分支合并到主分支之前检查新功能的代码更改或添加。

创建 AWS 代码提交存储库

在第三章中,介绍了 AWS CodeCommit,我介绍了如何在 AWS 管理控制台上创建 CodeCommit 存储库。在本章中,我们将更深入地了解创建 CodeCommit 存储库的各种方法,如 AWS 命令行界面(CLI)、CloudFormation、Terraform 和 AWS SDK。

使用 AWS 命令行界面(CLI)创建

必须首先安装和配置 AWS CLI。要开始使用 AWS CLI,必须使用有权执行预期操作的凭据进行配置。清单 6-8 展示了如何配置 AWS CLI 和一个示例输出。

$ aws configure
AWS Access Key ID [None]:
AWS Secret Access Key [None]:
Default region name [None]:
Default output format [None]:

Listing 6-8Configuring AWS CLI

配置 AWS CLI 环境后,可以创建一个带有示例输出的 CodeCommit 存储库,如清单 6-9 所示。

$ aws codecommit create-repository --repository-name devops-ios-repository --repository-description "Example Description"
{
    "repositoryMetadata": {
        "accountId": "123456789101",
        "repositoryId": "abcdedgh-6234-457b-b2c3-184babcdefgh",
        "repositoryName": "devops-ios-repository",
        "repositoryDescription": "Example Description",
        "lastModifiedDate": "2021-08-14T21:20:03.893000+00:00",
        "creationDate": "2021-08-14T21:20:03.893000+00:00",
        "cloneUrlHttp": "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/devops-ios-repository",
        "cloneUrlSsh": "ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/devops-ios-repository",
        "Arn": "arn:aws:codecommit:us-east-1:123456789101:devops-ios-repository"
    }
}

Listing 6-9Creating a CodeCommit repository with AWS CLI

使用 AWS CloudFormation 创建

要使用 CloudFormation 创建 CodeCommit 存储库,可以如清单 6-10 所示定义 CloudFormation 模板。

AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  RepositoryName:
    Type: String
    Default: devops-ios-repository
    Description: Name of the CodeCommit Repository

Resources:
  MyRepo:
    Type: AWS::CodeCommit::Repository
    Properties:
      RepositoryName: !Ref RepositoryName
      RepositoryDescription: Example Description

Listing 6-10CloudFormation template to create CodeCommit repository

如清单所示,CloudFormation 模板是 YAML 格式的,只包含一个 CodeCommit 资源。可以用这些 YAML 内容创建云形成堆栈,如图 6-2 所示。

图 6-2

使用 CloudFormation 创建 CodeCommit 知识库

存储库名称是参数化的,如清单 6-10 所示;默认名称在模板中定义,但可以修改。该参数可以在堆栈详情页面进行修改,如图 6-3 所示。

图 6-3

配置代码提交存储库的名称

图 6-4 显示了处于 CREATE_COMPLETE 状态的 CloudFormation 堆栈,这表示 CodeCommit 存储库已经创建。resources 选项卡显示了由 CloudFormation 堆栈创建的资源列表。

图 6-4

CodeCommit 云信息堆栈已创建

在 CodeCommit 控制台中可以看到创建的 CodeCommit 存储库,如图 6-5 所示。

图 6-5

代码提交存储库已创建

使用 Terraform 创建

必须首先参考 Terraform 官方文档安装和配置 Terraform。用于 CodeCommit 存储库创建的 Terraform 代码可以如清单 6-11 所示进行定义。

provider "aws" {
    region = "us-east-1"
}

resource "aws_codecommit_repository" "test" {
  repository_name = "devops-ios-repository"
  description     = "Example Description"
}

Listing 6-11Terraform code to create CodeCommit repository

代码应该保存在一个带有。tf 文件扩展名,并保存在专用的 Terraform 目录中,以用于预期的操作。在专用目录中,可以初始化 Terraform,如清单 6-12 所示。这里显示的操作下载了 Terraform 脚本中定义的资源所需的所有插件。

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v3.54.0...
- Installed hashicorp/aws v3.54.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the 

future.

Terraform has been successfully initialized!
...........................
...........................

Listing 6-12Initializing Terraform directory

您可以选择性地运行清单 6-13 中所示的terraform plan来查看 Terraform 将在您的 AWS 帐户中执行的操作,即创建、删除或修改资源。

$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_codecommit_repository.test will be created
  + resource "aws_codecommit_repository" "test" {
      + arn             = (known after apply)
      + clone_url_http  = (known after apply)
      + clone_url_ssh   = (known after apply)
      + description     = "Example Description"
      + id              = (known after apply)
      + repository_id   = (known after apply)
      + repository_name = "devops-ios-repository"
      + tags_all        = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Listing 6-13Terraform plan to see the actions Terraform will perform

初始化 Terraform 目录后,一旦您对清单 6-13 中所示的 Terraform 将采取的行动感到满意,就可以通过应用清单 6-14 中所示的 Terraform 脚本来创建资源。

$ terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_codecommit_repository.test will be created
  + resource "aws_codecommit_repository" "test" {
      + arn             = (known after apply)
      + clone_url_http  = (known after apply)
      + clone_url_ssh   = (known after apply)
      + description     = "Example Description"
      + id              = (known after apply)
      + repository_id   = (known after apply)
      + repository_name = "devops-ios-repository"
      + tags_all        = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

aws_codecommit_repository.test: Creating...
aws_codecommit_repository.test: Creation complete after 0s [id=devops-ios-repository]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Listing 6-14Applying Terraform script to create CodeCommit repository

使用 Python Boto3 SDK 创建

AWS 拥有针对不同编程语言的 SDK,使您能够使用自己喜欢的开发语言来管理和访问 AWS 服务。这里我将重点介绍名为 boto3 的 AWS Python SDK。要了解 boto3 SDK 的更多信息,请访问这里的官方文档: https://boto3.amazonaws.com/v1/documentation/api/latest/index.html

在安装 boto3 之前,您的工作站上需要 Python。假设安装了 Python,清单 6-15 展示了如何使用pip在工作站上安装 boto3。

$  pip install boto3

Listing 6-15Installing boto3

清单 6-16 中显示了一个使用 boto3 创建 CodeCommit 存储库的示例 Python 脚本。

import boto3

client = boto3.client('codecommit')

response = client.create_repository(
    repositoryName='devops-ios-repository',
    repositoryDescription='Example Description'
)

print(response

Listing 6-16Python script to create CodeCommit repository

在 boto3 可以创建资源之前,工作站必须配置有 AWS 凭证。可以用 AWS CLI 配置凭证,如清单 6-8 所示。

一旦工作站配置了 AWS 凭证,就可以执行 Python 脚本,如清单 6-17 所示。

$ python codecommit.py

{
    u'repositoryMetadata': {
        u'repositoryName': u'devops-ios-repository',
        u'cloneUrlSsh': u'ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/devops-ios-repository',
        u'lastModifiedDate': datetime.datetime(2021, 8, 14, 21, 53, 50, 718000, tzinfo=tzlocal()),
        u'repositoryDescription': u'Example Description',
        u'cloneUrlHttp': u'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/devops-ios-repository',
        u'creationDate': datetime.datetime(2021, 8, 14, 21, 53, 50, 718000, tzinfo=tzlocal()),
        u'repositoryId': u'3cd590f1-b898-43d7-b82c-eac6aef602a1',
        u'Arn': u'arn:aws:codecommit:us-east-1:123456789101:devops-ios-repository',
        u'accountId': u'123456789101'
    }, 

    'ResponseMetadata': {
        'RetryAttempts': 0,
        'HTTPStatusCode': 200,
        'RequestId': 'ff463517-219e-4d51-869f-fba5b1345c76',
        'HTTPHeaders': {
            'x-amzn-requestid': 'abcdefgh-219e-4d51-869f-fba5abcdefgh',
            'date': 'Sat, 14 Aug 2021 21:53:50 GMT',
            'content-length': '519',
            'content-type': 'application/x-amz-json-1.1'
        }
    }
}

Listing 6-17Running Python script to create CodeCommit repository

在 AWS 代码提交中添加源代码

正如我们所知,CodeCommit 是一个私有的 Git 存储库,但由于它是一个 AWS 服务,AWS 的核心基础仍然适用,例如在连接到存储库时使用身份访问管理(IAM)进行授权和认证。

让我们探索连接到 CodeCommit 存储库和存储源代码的不同选项。

连接到代码提交存储库

有各种选项可用于连接到 CodeCommit 存储库。适合您的选项将取决于您使用 AWS 服务的身份验证方式。例如,它是否是 IAM 用户、IAM 角色、联合访问等。?

对于连接到 CodeCommit 存储库的每种方法,使用的 URL 是不同的;对于特定的存储库,可以检索每个连接方法的 URL,如图 6-6 所示。

图 6-6

CodeCommit 连接 URL

安全超文本传输协议

HTTPS 方法用于 IAM 用户,它涉及为该 IAM 用户生成 Git 用户名和密码。生成的用户名和密码在执行 Git 操作时用作 Git 凭证。

要为 IAM 用户生成 Git 用户名和密码,请转到 IAM 用户的安全凭证设置,如图 6-7 所示。

图 6-7

IAM 用户的安全凭据设置

在 IAM 用户的安全凭证页面中,可以看到为 AWS CodeCommit 生成 HTTPS Git 凭证的选项,如图 6-8 所示。

图 6-8

正在生成 HTTPS Git 凭据

生成凭证后,您可以下载. csv 文件形式的凭证或复制用户名和密码,如图 6-9 所示。

图 6-9

正在下载生成的 HTTPS 凭据

通过克隆一个新创建的存储库,生成的凭证可以用来连接到一个带有 HTTPS URL 的 CodeCommit 存储库,如清单 6-18 所示。

$ git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/devops-ios-repository
Cloning into 'devops-ios-repository'...
Username for 'https://git-codecommit.us-east-1.amazonaws.com': abdullahi-at-168181944806

Password for 'https://abdullahi-at-168181944806@git-codecommit.us-east-1.amazonaws.com':
warning: You appear to have cloned an empty repository.
$ cd devops-ios-repository/
$ git status

On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Listing 6-18Connect to CodeCommit repository with HTTPS

与 HTTPS 方法类似,连接到 AWS CodeCommit 存储库的 SSH 方法也用于 IAM 用户;这种连接方法需要一对私钥和公钥。公钥与 IAM 用户相关联,而私钥在 Git 工作站中本地配置。使用 SSH 连接方法的第一步是使用ssh-keygen生成一个 SSH 密钥对,如清单 6-19 所示。

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/cloudshell-user/.ssh/id_rsa): /home/cloudshell-user/.ssh/codecommit_key
Created directory '/home/cloudshell-user/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/cloudshell-user/.ssh/codecommit_key.
Your public key has been saved in /home/cloudshell-user/.ssh/codecommit_key.pub.
The key fingerprint is:
SHA256:AJ1EUBde/TT0K/D6SqaryVdSEalDPVN8K/Lp55yWPrU cloudshell-user@ip-10-1-34-183.ec2.internal
The key's randomart image is:
+---[RSA 2048]----+
|    o*+.o.oo=o.  |
|     .oo o *..oo |
|      . o ..+o..o|
|       . o oo....|
|        S o ooo. |
|         . ..o. .|
|          o+.   +|
|      . ..+ ...E.|
|       +oo....==.|

+----[SHA256]-----+

Listing 6-19Generating SSH key pair

清单 6-19 中生成的密钥对被命名为 codecommit_key,因此生成的公钥将被命名为 codecommit_key.pub,而私钥是 codecommit_key,两者都存储在目录 /home/cloudshell-user/中。宋承宪

接下来,为预期的 IAM 用户将公钥上传到 AWS。要上传 IAM 用户的 SSH 公钥,请访问安全凭证设置,如图 6-7 所示。在安全凭证中,开始上传的选项如图 6-10 所示。

图 6-10

开始 SSH 公钥上传

将提供 SSH 公钥的内容,如图 6-11 所示。在本例中,这是 codecommit_key.pub 的内容。您可以检索清单 6-20 中所示的内容。

图 6-11

添加 SSH 公钥内容

$ cat ~/.ssh/codecommit_key.pub

Listing 6-20Retriving SSH public key content

公钥上传成功后,生成 SSH 密钥 ID,如图 6-12 所示。检索 SSH 密钥 ID,因为它将用于本地 Git 配置。

图 6-12

上传的公钥的 SSH 密钥 ID

本地 Git 配置存储在。ssh 文件夹,如清单 6-21 所示。配置文件中的主机字段是跨所有区域的 CodeCommit URL 模式,用户字段是应该用于连接的 SSH 用户,(这是从 AWS IAM 检索的 SSH 密钥 ID,如图 6-12 所示),而标识文件字段指向存储 SSH 私钥的位置。

$ vim ~/.ssh/config

Host git-codecommit.*.amazonaws.com
User APKASOKDM2HTO6CTLRZS
IdentityFile ~/.ssh/codecommit_key

Listing 6-21Local SSH configuration

读写权限也应该添加到配置文件权限中,如清单 6-22 所示。

$ chmod 600 .ssh/config

Listing 6-22Setting config file permission

现在配置了 SSH,您可以通过克隆一个新创建的存储库,用它的 SSH URL 连接到 CodeCommit 存储库,如清单 6-23 所示。

$ git clone ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/devops-ios-repository
Cloning into 'devops-ios-repository'...
The authenticity of host 'git-codecommit.us-east-1.amazonaws.com (52.94.229.29)' can't be established.
RSA key fingerprint is SHA256:eLMY1j0DKA4uvDZcl/KgtIayZANwX6t8+8isPtotBoY.
RSA key fingerprint is MD5:a6:9c:7d:bc:35:f5:d4:5f:8b:ba:6f:c8:bc:d4:83:84.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'git-codecommit.us-east-1.amazonaws.com,52.94.229.29' (RSA) to the list of known hosts.
warning: You appear to have cloned an empty repository.
$ cd devops-ios-repository/
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Listing 6-23Connecting to CodeCommit repository with SSH

Git 远程代码提交(GRC)

当您使用具有 IAM 角色的临时凭据来连接 AWS 时,会使用此选项。临时凭证的常见用例是身份联合、跨帐户访问和 AWS 服务(如 EC2)的角色。

GRC 是一个必须安装在工作站上的工具(git-remote-codecommit),在这种方法中,GRC 获取执行 git 操作的用户的当前 AWS 凭据,并使用它们对 codecommit 进行身份验证;因此,不需要 IAM 永久用户。

GRC 需要安装 Python,可以用 pip 安装,如清单 6-24 所示。

$ pip install git-remote-codecommit

Listing 6-24Installing Git remote CodeCommit

为了演示 git-remote-codecommit 如何工作,我将假设一个 IAM 角色,并使用为 IAM 角色生成的临时凭证来连接到存储库。

将要承担的 IAM 角色的配置如图 6-13 所示。

图 6-13

具有 AWS 代码提交权限的 IAM 角色

为了获得临时凭证,我将使用 AWS CLI 承担 IAM 角色,如清单 6-25 所示。其中如图 6-13 所示的角色 ARN 被传递给--role-arn标志,并且在--role-session-name标志中为会话名称提供一个描述性名称。

$ aws sts assume-role --role-arn "arn:aws:iam::123456789101:role/CodeCommitRole" --role-session-name AWSCLI-Session

Listing 6-25Assuming IAM role

此 AWS CLI 操作返回临时凭据作为输出,并返回凭据的过期信息。检索 AccessKeyIdSecretAccessKeySessionToken ,配置将要执行 Git 操作的工作站,如清单 6-26 所示。

$ export AWS_ACCESS_KEY_ID=<RoleAccessKeyID>
$ export AWS_SECRET_ACCESS_KEY=<RoleSecretAccessKey>
$ export AWS_SESSION_TOKEN=<RoleSessionToken>

Listing 6-26Configure workstation with temporary credentials

您的工作站现在应该正在使用临时凭证。您可以验证临时凭证是否配置正确并且是活动的,如清单 6-27 所示。

$ aws sts get-caller-identity
{
    "UserId": "AROASOKDM2HTNVOJHAAV7:AWSCLI-Session",
    "Account": "123456789101",
    "Arn": "arn:aws:sts::123456789101:assumed-role/CodeCommitRole/AWSCLI-Session"
}

Listing 6-27Verifying temporary credentials

在验证临时凭证是活动的之后,我可以通过克隆一个新创建的存储库,使用 GRC URL 连接到存储库,如清单 6-28 所示。

$ git clone codecommit::us-east-1://devops-ios-repository
Cloning into 'devops-ios-repository'...
warning: You appear to have cloned an empty repository.
$ cd devops-ios-repository/
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

Listing 6-28Connecting to CodeCommit repository with Git remote CodeCommit

将代码推送到代码提交存储库

现在,我们已经探索了通过在本地克隆一个空的 CodeCommit 存储库来连接到 CodeCommit 存储库的不同方法,让我们向本地存储库添加一些源代码,并将更改推送到 CodeCommit。

在将源代码添加到本地目录但还没有提交到 Git 之后,可以检查存储库的状态,如清单 6-29 所示,在这里您会看到新文件被列为未跟踪。

$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        SampleApp.xcodeproj/
        SampleApp/
        SampleAppTests/
        SampleAppUITests/

nothing added to commit but untracked files present (use "git add" to track)

Listing 6-29Checking the status of new files added to local repository

然后,新添加的文件被暂存并提交给 Git,如清单 6-30 所示。

$ git add .
$ git commit -m "Add Sample Application Code"
[master (root-commit) 4c25bde] Add Sample Application Code
 34 files changed, 981 insertions(+)
 create mode 100644 SampleApp.xcodeproj/project.pbxproj
 create mode 100644 SampleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
 create mode 100644 SampleApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
 create mode 100644 SampleApp.xcodeproj/project.xcworkspace/xcuserdata/olaoyea.xcuserdatad/UserInterfaceState.xcuserstate
 create mode 100644 SampleApp.xcodeproj/xcuserdata/olaoyea.xcuserdatad/xcschemes/xcschememanagement.plist
 create mode 100644 SampleApp/Assets.xcassets/AccentColor.colorset/Contents.json
 create mode 100644 SampleApp/Assets.xcassets/AppIcon.appiconset/1024.png
 create mode 100644
...................................................
...................................................
...................................................

Listing 6-30Committing source code to Git

然后,通过简单地运行 Git push 将更改推送到 CodeCommit,如清单 6-31 所示。

  • CodeCommit SSH URL 用于此操作。
$ git push
Warning: Permanently added the RSA host key for IP address '52.94.233.146' to the list of known hosts.
Enumerating objects: 45, done.
Counting objects: 100% (45/45), done.
Delta compression using up to 2 threads
Compressing objects: 100% (40/40), done.
Writing objects: 100% (45/45), 75.21 KiB | 6.84 MiB/s, done.
Total 45 (delta 1), reused 0 (delta 0)
To ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/devops-ios-repository

 * [new branch]      master -> master

Listing 6-31Pushing changes to CodeCommit

将 Git 存储库迁移到 AWS 代码提交

现有的远程 Git 存储库也可以迁移到 CodeCommit。要迁移到 CodeCommit,将在本地克隆存储库,然后将其推送到目标 CodeCommit 存储库。

例如,我想将一个名为devo PS-on-AWS-IOs-development的私有 GitHub 存储库迁移到一个名为target-CodeCommit-repository的 CodeCommit 存储库。首先,我将源 GitHub 存储库克隆到一个临时的本地目录,我将其命名为 migrate-to-codecommit ,如清单 6-32 所示。传递的--mirror标志用于克隆用于迁移的远程存储库的裸副本。

$ git clone --mirror https://github.com/abdulola/devops-on-aws-ios-development.git migrate-to-codecommit
Cloning into bare repository 'migrate-to-codecommit'...
Username for 'https://github.com': abdulola
Password for 'https://abdulola@github.com':
remote: Enumerating objects: 97, done.
remote: Counting objects: 100% (97/97), done.
remote: Compressing objects: 100% (79/79), done.
remote: Total 97 (delta 11), reused 86 (delta 7), pack-reused 0
Unpacking objects: 100% (97/97), done.

Listing 6-32Cloning source GitHub repository to local directory

接下来,我将进入本地目录,然后将内容推送到目标 CodeCommit 存储库,如清单 6-33 所示。--all标志确保存储库的所有分支都被推送到目标 CodeCommit 存储库。

$ cd migrate-to-codecommit/
$ git push --all ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/target-codeommit-repository
Enumerating objects: 97, done.
Counting objects: 100% (97/97), done.
Delta compression using up to 2 threads
Compressing objects: 100% (86/86), done.
Writing objects: 100% (97/97), 291.28 KiB | 10.40 MiB/s, done.
Total 97 (delta 11), reused 0 (delta 0)
To ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/target-codeommit-repository
 * [new branch]      main -> main

Listing 6-33Pushing contents to the destination CodeCommit repository

此时,GitHub 库已经迁移到 AWS CodeCommit,临时本地目录 migrate-to-codecommit 可以删除了。新迁移的仓库如图 6-14 所示。

图 6-14

CodeCommit 中迁移的存储库

要开始与 CodeCommit 存储库交互,您必须将存储库克隆到本地。清单 6-34 显示了临时迁移目录的删除和本地迁移存储库的克隆。

  • CodeCommit SSH URL 用于此操作。
$ rm -rf migrate-to-codecommit/
$ git clone ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/target-codeommit-repository
Cloning into 'target-codeommit-repository'...
Warning: Permanently added the RSA host key for IP address '52.94.226.180' to the list of known hosts.
remote: Counting objects: 97, done.
Receiving objects: 100% (97/97), 291.28 KiB | 15.33 MiB/s, done.
Resolving deltas: 100% (11/11), done

.

Listing 6-34Cloning migrated repository to local

AWS 代码提交中分支

在 CodeCommit 中创建分支有不同的方法,当您第一次提交到 CodeCommit 存储库时,会创建一个名为 main 的默认分支。接下来,我将向您展示如何使用 AWS 控制台、Git 和 AWS CLI 创建额外的分支。

在 AWS 控制台上创建分支

从 CodeCommit 存储库控制台中,选择分支菜单,如图 6-15 所示。

图 6-15

从代码提交存储库控制台访问分支菜单

  • 上一节中迁移到 CodeCommit 的存储库用于本练习。

在下一页开始创建分支,如图 6-16 所示。如前所述,存储库的默认分支已经存在。

图 6-16

开始分支创建

创建分支时,必须选择要从中创建新分支的分支。如图 6-17 所示,一个名为 dev 的分支正在从唯一存在的分支 main 中创建。

图 6-17

创建新的开发分支

创建的新开发分支可以在图 6-18 中看到。两个分支的最后一个提交消息是相同的,这是因为 dev 分支是新创建的,没有添加额外的提交。

图 6-18

创建了新的开发分支

用 Git 创建分支

CodeCommit 中的新分支也可以从 Git 命令行使用 Git 创建。当从 Git 命令行创建分支时,最初只在本地创建,必须将分支推送到 CodeCommit,以便在 CodeCommit 上创建。

清单 6-35 显示了在本地创建一个新的分支,以及在 CodeCommit 上创建这个分支的推送操作。

  • 上一节中迁移到 CodeCommit 的存储库用于本练习。本地存储库已经从清单 6-34 中的 Git 克隆操作链接到 CodeCommit 存储库。
$ cd target-codeommit-repository/
$ git checkout -b test
Switched to a new branch 'test'
$ git push origin test
Total 0 (delta 0), reused 0 (delta 0)
To ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/target-codeommit-repository
 * [new branch]      test -> test

Listing 6-35Create CodeCommit branch using Git

在 CodeCommit 控制台上可以看到新创建的分支测试,如图 6-19 所示。

图 6-19

从 Git 创建的新测试分支

使用 AWS CLI 创建分支

要使用 AWS CLI 创建分支,除了将存储库名称和分支名称作为参数传递之外,还必须指定要从中创建分支的 Git commit ID。要检索 Git 提交 ID,您可以访问您的 CodeCommit 存储库的所有提交,如图 6-20 所示。

图 6-20

访问代码提交资料档案库的所有提交

您可以复制提交 ID 来创建新的分支,如图 6-21 所示。

图 6-21

复制提交 ID

知道了用于分支创建的提交 ID 后,就可以使用 AWS CLI 创建新的分支,如清单 6-36 所示。

$ aws codecommit create-branch --repository-name target-codeommit-repository --branch-name preprod --commit-id 7da70dd7ef5eb237012ac0699367922d9cb3524e

Listing 6-36Creating branch using AWS CLI

如图 6-22 所示,可以在代码提交控制台上看到新创建的预编程分支。

图 6-22

使用 AWS CLI 创建新的预编程分支

更新本地存储库

随着所有新分支的创建,一些分支存在于 CodeCommit 中,但不在本地,您可以获取远程存储库的更新并查看所有分支,如清单 6-37 所示。

$ git remote update origin
Fetching origin
From ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/target-codeommit-repository
 * [new branch]      preprod    -> origin/preprod

$ git branch --all
  dev
* test
  remotes/origin/HEAD -> origin/dev
  remotes/origin/dev

  remotes/origin/main
  remotes/origin/preprod
  remotes/origin/test

Listing 6-37Fetch update from remote repository

配置默认分支

当您第一次提交到 CodeCommit 存储库时,会为您创建一个名为 main 的默认基础分支。如果需要,可以将这个默认分支更改为存储库中的其他分支。要更改默认分支,请转到如图 6-23 所示的存储库设置。

图 6-23

存储库设置

默认分支菜单中,可以从库分支列表中选择新的默认分支,如图 6-24 所示。

图 6-24

选择默认分支

AWS 代码提交中的拉请求

AWS 代码提交存储库支持在合并分支之前创建拉请求。还有一些额外的特定于 CodeCommit 的 pull request 特性,比如批准规则和 Amazon CodeGuru Reviewer 集成。接下来让我们探索所有这些概念。

创建拉取请求

当两个分支合并时,例如,一个功能分支与一个主分支合并,可以在 AWS 控制台或 CLI 上创建一个拉请求。

在您可以创建一个拉请求来合并两个分支之前,这两个分支之间必须有一个增量。一个增量被引入到本地存储库中的一个测试分支,并被推送到远程代码提交存储库中,如清单 6-38 所示。

$ echo "Add New Text" >> README.md
$ git status
On branch test
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   README.md

no changes added to commit (use "git add" and/or "git commit -a")
$ git add README.md
$ git commit -m "Add new text to Readme"
[test 7ea6176] Add new text to Readme

 1 file changed, 1 insertion(+)

$ git push --set-upstream origin test
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 311 bytes | 311.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/target-codeommit-repository

   7da70dd..7ea6176  test -> test
Branch 'test' set up to track remote branch 'test' from 'origin'.

Listing 6-38Adding changes to repository test branch and pushing to CodeCommit

既然代码更改已经被推送到 CodeCommit 存储库的测试分支,就可以创建一个 pull 请求了。

AWS 控制台

要创建一个拉请求,您可以访问存储库的拉请求页面,如图 6-25 所示。

图 6-25

访问拉取请求控制台

在存储库的 Pull requests 页面上,您可以开始创建 Pull requests,如图 6-26 所示。

图 6-26

开始创建拉取请求

如图 6-27 所示选择源和目的分支。对于这个例子,包含代码变更的源分支是测试,目标分支是

图 6-27

选择源和目标分支

为拉取请求提供标题和可选描述,如图 6-28 所示。通常,该描述将包含代码更改的细节,以便为将要审查它的团队成员提供上下文。

图 6-28

为拉取请求提供标题和描述

在最终创建拉请求之前,您可以检查由源分支引入的变更,如图 6-29 所示。

图 6-29

查看由“拉”请求引入的更改

最后,一旦成功创建了拉请求,新的拉请求将如图 6-30 所示。

图 6-30

已创建拉取请求

AWS CLI

为了在 AWS CLI 上创建一个拉请求,我们使用清单 6-39 中的命令。拉请求标题被传递给--title选项,描述被传递给--description选项,您生成的惟一幂等令牌应该被传递给--client-request-token选项,存储库和分支信息被传递给--targets选项。

$ aws codecommit create-pull-request --title "Merge Test to Main Branch" --description "Example description" --client-request-token Example --targets repositoryName=target-codeommit-repository,sourceReference=Test,destinationReference=main

Listing 6-39Creating pull request with the AWS CLI

合并拉取请求

一旦“拉”请求被其他人审阅并准备好合并,这个操作也可以在 AWS 控制台或 CLI 上执行。

AWS 控制台

只要两个分支是可合并的,即没有合并冲突或批准规则会阻止合并,合并选项总是被激活,如图 6-31 所示。

图 6-31

开始提取请求合并

要合并,必须选择一个合并策略;CodeCommit 支持三种不同的合并策略,如图 6-32 所示。合并的默认 Git 行为是尽可能快进。如果由于合并方案而无法应用特定的合并类型,此选项将灰显且无法选择。成功合并后,您可以选择删除源分支,选择此选项后,本例中使用的测试分支将从存储库中删除。

图 6-32

选择合并类型和合并提取请求

一旦拉请求被成功合并,你会得到一个确认,如图 6-33 所示。

图 6-33

已合并拉取请求

要查看所应用的合并更改,您可以切换到存储库中的目标分支,并检查由 pull 请求所做的文件更改。如图 6-34 所示,拉取请求更新的仓库的 README.md 已经被更改。

图 6-34

来自拉取请求的更新文件

现在远程分支已经更新,为了保持本地分支也是最新的,必须执行一个git pull操作,如清单 6-40 所示。

$ git pull
From ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/target-codeommit-repository
   7da70dd..7ea6176  main       -> origin/main
Your configuration specifies to merge with the ref 'refs/heads/test'
from the remote, but no such ref was fetched.

$ git checkout main
Branch 'main' set up to track remote branch 'main' from 'origin'.
Switched to a new branch 'main'

Listing 6-40Updating local main branch with changes from remote

AWS CLI

要在 AWS CLI 上合并拉请求,要执行的命令取决于要应用的合并策略。清单 6-41 展示了如何使用快进合并策略进行合并。拉请求 ID 被传递给--pull-request-id选项,来自源分支的最新完整提交 ID 被传递给--source-commit-id选项,最后,存储库名称被传递给--repository-name选项。

$ aws codecommit merge-pull-request-by-fast-forward --pull-request-id 1 --source-commit-id EXAMPLE1112222333 --repository-name target-codeommit-repository

Listing 6-41Merging using fast forward strategy

创建审批规则模板

批准规则模板允许您自动将批准规则应用于在存储库中创建的提取请求。在每个 AWS 区域中,您可以将批准规则模板应用于在所有 CodeCommit 存储库中创建的部分或全部拉请求。

使用批准规则模板,您可以在为给定分支(例如,您的主分支)创建提取请求时自动应用批准规则,并在合并提取请求之前要求某些团队成员的批准。

让我们看看如何在 AWS 控制台和 CLI 上创建批准模板。

AWS 控制台

您可以在 AWS 控制台上访问审批规则模板页面,如图 6-35 所示。

图 6-35

访问审批规则模板页面

您可以开始创建审批规则模板,如图 6-36 所示。

图 6-36

开始创建审批规则模板

我正在创建的审批规则模板定义如图 6-37 所示。批准的最小数量定义为 1,还提供了有效批准人的列表。这里我提供一个 I am 用户的 ARN;还指定了要应用规则的目标分支。最后,指定要应用该模板的存储库列表。

图 6-37

审批规则模板定义

AWS CLI

要在 AWS CLI 上创建批准规则模板,必须首先在 JSON 中定义该模板,如清单 6-42 所示。定义的示例模板应用于存储库的主分支,需要两次批准,批准者列表中提供了 IAM 用户 ARN。

{
  "Version": "2018-11-08",
  "DestinationReferences": [
    "refs/heads/main"
  ],
  "Statements": [
    {
      "Type": "Approvers",
      "NumberOfApprovalsNeeded": 2,
      "ApprovalPoolMembers": [
        "arn:aws:iam::123456789101:user/abdullahi"
      ]
    }
  ]
}

Listing 6-42Approval rule template definition

该模板可以提供给 AWS CLI 命令,如清单 6-43 所示。审批模板名称在--approval-rule-template-name选项中提供,描述在--approval-rule-template-description选项中提供,模板 JSON 定义在--approval-rule-template-content选项中提供。

$ aws codecommit create-approval-rule-template --approval-rule-template-name Engineering-Manager-Approval --approval-rule-template-description "Requires Engineering Manager Approval" --approval-rule-template-content "{\"Version\":\"2018-11-08\",\"DestinationReferences\":[\"refs\/heads\/main\"],\"Statements\":[{\"Type\":\"Approvers\",\"NumberOfApprovalsNeeded\":2,\"ApprovalPoolMembers\":[\"arn:aws:iam::123456789101:user\/abdullahi\"]}]}"

{
    "approvalRuleTemplate": {
        "approvalRuleTemplateId": "d812838a-4010-4c68-80ce-e03b8ba456c7",
        "approvalRuleTemplateName": "Engineering-Manager-Approval",
        "approvalRuleTemplateDescription": "Requires Engineering Manager Approval",
        "approvalRuleTemplateContent": "{\"Version\":\"2018-11-08\",\"DestinationReferences\":[\"refs/heads/main\"],\"Statements\":[{\"Type\":\"Approvers\",\"NumberOfApprovalsNeeded\":2,\"ApprovalPoolMembers\":[\"arn:aws:iam::123456789101:user/abdullahi\"]}]}",
        "ruleContentSha256": "609e9411c4a0a04d8f49438ac4faa377393355ba831646637f5895a4283aa732",
        "lastModifiedDate": "2021-08-18T00:23:22.780000+00:00",
        "creationDate": "2021-08-18T00:23:22.780000+00:00",
        "lastModifiedUser": "arn:aws:iam::123456789101:user/abdullahi"
    }
}

Listing 6-43Creating an approval rule template from the AWS CLI

带有审批规则模板的拉取请求

如果您创建了拉取请求,并且已将批准规则模板应用于存储库,并且批准规则模板中定义的分支与拉取请求的目标分支相匹配,则无需任何进一步的操作,即可为拉取请求创建批准规则。审批规则的条件在审批规则模板中定义。

图 6-38 显示了一个 pull 请求,它被创建来将 dev 分支合并到我们的示例 CodeCommit 存储库的主分支。审批规则被应用于该拉取请求,因为如图 6-37 所示创建的审批规则模板应用于该存储库和分支。因为我使用在批准规则模板的批准者列表中指定的 I am 用户登录 AWS 控制台,所以我看到可用的批准选项。

图 6-38

应用审批规则的提取请求

一旦拉动请求被批准,批准规则要求就被满足,合并按钮出现,如图 6-39 所示。

图 6-39

审批后合并拉取请求

Amazon CodeGuru Reviewer 集成

Amazon CodeGuru reviewer 是一个 AWS 服务,它使用机器学习来检测代码中的缺陷,CodeGuru reviewer 可以与 CodeCommmit 存储库相关联。当在与 CodeGuru 评审者相关联的存储库中创建一个拉请求时,它会自动开始评审该拉请求,并将发现和建议作为注释添加到拉请求中。

目前 CodeGuru reviewer 只支持审查 Java 和 Python 代码。

协会代码专家评审员

要将 CodeGuru reviewer 与 CodeCommit 存储库相关联,请访问存储库设置中的 Amazon CodeGuru Reviewer 选项卡,如图 6-40 所示。

图 6-40

CodeCommit 存储库设置中的 CodeGuru Reviewer 选项卡

将 CodeGuru Reviewer 关联到您的 CodeCommit 存储库,如图 6-41 所示。

图 6-41

协会代码专家评审员

关联不会立即完成,而关联状态是关联。如图 6-42 所示,关联需要 10 分钟。

图 6-42

CodeGuru 审阅者关联正在进行中

关联完成后,状态变为关联。解除存储库关联的选项也会出现,如图 6-43 所示。

图 6-43

CodeGuru 审查者关联

查看拉取请求

让我们通过用 Python 代码创建一个 pull 请求来看看 CodeGuru Reviewer 是如何工作的。为了触发 CodeGuru reviewer 的评论,我将使用一个有缺陷的 Python 代码。要使用的 Python 代码如清单 6-44 所示;这是一个简单的代码,列出了 S3 桶中的所有对象。

import boto3

s3_client = boto3.client('s3')
s3_client.list_objects(Bucket="BucketName")

Listing 6-44Example Python code to trigger CodeGuru reviewer

我将这个代码片段添加到我的存储库的 dev 分支中的一个. py 文件中,并创建一个 pull 请求来合并到分支中。CodeGuru reviewer 自动开始审查 pull 请求,如图 6-44 所示。

图 6-44

CodeGuru 审核者审核拉取请求

完成审查后,如果在拉请求中发现任何缺陷,它会留下一个注释。如图 6-45 所示,我在代码中使用了一个过时的 API,CodeGuru reviewer 建议使用修改后的 API。

图 6-45

查看 CodeGuru 评论

摘要

iOS 应用开发流程的自动化和编排始于源代码控制管理。在这一章中,我们介绍了 Git 版本控制系统的基础知识,然后深入探讨了 AWS CodeCommit 的 Git 特性,以及如何使用它作为一个私有的远程 Git 存储库,并附有演练示例。然后,我们介绍了它与 Amazon CodeGuru Reviewer 的集成,通过机器学习自动审查 Python 和 Java 代码。

七、将 AWS CodeCommit 与 Jenkins 集成

当应用源代码存储在 AWS CodeCommit 中以进行源代码控制时,它可以与其他构建和测试系统集成以进行持续集成,以便当在源存储库中进行新的提交时,触发自动构建和/或测试。

在本章中,我们将看到 AWS CodeCommit 如何使用 Jenkins 插件与 Jenkins 集成。通过这种集成,可以使用 AWS CodeCommit for source control 在 Jenkins 上设置 iOS 应用构建作业,其中当代码提交到 AWS CodeCommit 时,在 Jenkins 上触发构建。

Jenkins 代码提交插件

插件用于增强 Jenkins 的功能,以适应特定的用例,它允许各种工具和云提供商与 Jenkins 集成。为了集成 AWS CodeCommit 和 Jenkins,使用了一个 AWS CodeCommit 插件。

当通过亚马逊简单通知服务(SNS)进行提交时,Jenkins AWS CodeCommit 插件通过向亚马逊简单队列服务(SQS)队列发送消息来工作。Jenkins 作业定期轮询队列中的任何新消息,如果发现新消息,则触发作业的新构建。

要在 Jenkins 控制器上安装该插件,图 7-1 显示了如何从 Jenkins 环境主页访问管理 Jenkins 页面。

图 7-1

访问管理 Jenkins 控制台

在设置控制台上,有各种配置 Jenkins 环境的选项,如图 7-2;您可以访问“管理插件”页面来管理插件。

图 7-2

管理 Jenkins 插件

所有安装在 Jenkins 环境中的插件都可以在这个页面上管理,从不同的可用选项卡可以看到。 Updates 选项卡显示任何已安装的插件,该更新了, Available 选项卡显示可以安装在 Jenkins 环境中的所有可用插件, Installed 选项卡显示安装在该 Jenkins 环境中的所有 Jenkins 插件, Advanced 选项卡提供执行操作的选项,如通过手动上传档案来安装插件。使用高级选项的一个用例是当您想要安装一个通过 web UI 不可用的插件的旧版本时。

要开始安装 AWS CodeCommit 插件,切换到 Available 选项卡并搜索 CodeCommit,如图 7-3 所示。

图 7-3

正在搜索 AWS 代码提交插件

选择 AWS CodeCommit 触发器并安装,如图 7-4 所示。你可以指示 Jenkins 立即安装而不重启,或者下载并等待下次重启来安装插件。

图 7-4

正在安装 AWS 代码提交插件

现在已经安装了插件,要开始在项目中使用插件,必须对它进行配置。但是,要配置该插件,作为先决条件,需要设置一些 AWS 资源。

在下一节中,我们将看到如何设置这些先决资源。

设置集成组件

要配置在上一节中安装的 AWS CodeCommit Jenkins 插件,我们需要创建一个 Amazon SQS 队列和 Amazon SNS 主题,并配置 CodeCommit 存储库,以便在创建新的提交时将消息发布到 SQS 队列。

通过 AWS 控制台设置组件

在本节中,我们将通过 AWS 控制台手动设置这些组件。

正在创建 SQS 队列

要访问亚马逊简单队列服务(SQS)控制台,在 AWS 控制台上搜索 SQS ,如图 7-5 所示。

图 7-5

在 AWS 管理控制台上搜索 SQS

开始创建 SQS 队列,如图 7-6 所示。

图 7-6

开始创建 SQS 队列

图 7-7 显示了如何配置 SQS 队列的示例。对于这个用例,标准队列类型就足够了。

图 7-7

配置和创建 SQS 队列

创建 SNS 主题和订阅 SQS 队列

要访问亚马逊简单通知服务(SNS)控制台,在 AWS 控制台上搜索 SNS ,如图 7-8 所示。

图 7-8

在 AWS 管理控制台上搜索 SNS

开始创建一个 SNS 主题,如图 7-9 所示。

图 7-9

开始创建 SNS 主题

SNS 主题的配置示例如图 7-10 所示。标准的 SNS 主题类型适合这个用例。

图 7-10

配置和创建 sns 主题

既然已经创建了一个 SQS 队列和一个 SNS 主题,那么通过为 SNS 主题订阅 SQS 队列,这两个队列将被集成在一起。SNS 主题向其订阅的所有实体发布消息;当 SQS 队列接收到来自 SNS 主题的消息时,它会存储该消息,直到消费者使用队列中的消息。在这种情况下,消费者是运行在 Jenkins 中的 AWS CodeCommit 插件。

访问创建的 SNS 主题并创建订阅,如图 7-11 所示。

图 7-11

开始创建订阅

由于订阅是为 SQS 队列创建的,因此应该相应地选择亚马逊 SQS 协议和相应的 SQS 队列,如图 7-12 所示。

图 7-12

配置和创建亚马逊 SQS 订阅

成功创建 SQS 订阅的示例如图 7-13 所示。

图 7-13

成功创建 SQS 订阅

设置 SQS 队列权限

要允许 SNS 主题向 SQS 队列发布消息,应该将 SQS 队列的访问策略配置为允许访问 SNS 主题。要配置 SQS 队列访问策略,从 SQS 队列进入访问策略页签,如图 7-14 所示。

图 7-14

配置 SQS 队列访问策略

默认情况下,帐户中的 IAM 身份可以访问创建的 SQS 队列,但是要允许访问 SNS 等 AWS 服务,需要修改访问策略。

清单 7-1 显示了一个示例策略,该策略可以应用于访问策略,以允许 SNS 主题向 SQS 队列发布消息。

  • 要使用此示例策略,请更改帐户 id 和资源名称以与您的相匹配。
{
  "Version": "2008-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "__owner_statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789101:root"
      },
      "Action": "SQS:*",
      "Resource": "arn:aws:sqs:us-east-1:123456789101:codecommit-trigger-queue"
    }
  ,
  {
    "Effect":"Allow",
    "Principal": {
      "Service": "sns.amazonaws.com"
    },
    "Action":"sqs:SendMessage",
    "Resource":"arn:aws:sqs:us-east-1:123456789101:codecommit-trigger-queue",
    "Condition":{
      "ArnEquals":{
        "aws:SourceArn":"arn:aws:sns:us-east-1:123456789101:codecommit-trigger-topic"
      }
    }
  }]
}

Listing 7-1SQS queue access policy

测试 SQS 和社交网络整合

随着 SQS 队列访问策略的配置,亚马逊 SQS 和亚马逊 SNS 的集成就完成了。可以通过在 SNS 主题中手动发布消息并验证消息是否在 SQS 队列中收到来测试集成。

在 SNS 话题上发布消息,如图 7-15 所示。

图 7-15

社交网络发布消息

提供测试消息主题和消息体,如图 7-16 所示。该消息将被分发给订阅 SNS 主题的所有实体。

图 7-16

提供测试消息主题和正文

切换到 SQS 队列控制台,验证消息是否已收到。在 SQS 队列上,您可以开始接收如图 7-17 所示的消息。

图 7-17

正在 SQS 队列上接收消息

可以轮询和查看消息,如图 7-18 所示。将显示队列中的所有消息。要轮询消息,点击轮询消息选项,如图 7-18 所示。

图 7-18

轮询和查看 SQS 队列中的消息

队列中的消息验证从 SNS 发布的消息是否被传递到 SQS。

要查看消息内容,点击消息 ID,如图 7-18 所示。消息内容将类似于清单 7-2 。

{
  "Type": "Notification",
  "MessageId": "f1ddce6c-0f19-5961-8413-97ad8d705b83",
  "TopicArn": "arn:aws:sns:us-east-1:123456789101:codecommit-trigger-topic",
  "Subject": "Test Message",
  "Message": "Test Message",
  "Timestamp": "2021-09-19T18:23:37.676Z",
  "SignatureVersion": "1",
  "Signature": "PPp9ZRsxc8/TY**************",
  "SigningCertURL": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-7ff5318490ec183fbaddaa2a969abfda.pem",
  "UnsubscribeURL": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456789101:codecommit-trigger-topic:7272ea84-728e-4fdb-9e15-6a02e9c5b2f1"
}

Listing 7-2SQS message received from SNS topic

配置代码提交存储库触发器

如前几节所示,已经创建了一个 SQS 队列和一个 SNS 主题。要设置的最后一个组件是在 AWS CodeCommit 上配置触发器。CodeCommit trigger 允许您在存储库事件发生时触发操作。

您可以配置特定存储库事件或所有存储库事件来触发操作。对于操作,您可以调用 AWS lambda 函数或向 Amazon SNS 主题发送通知。我们将了解存储库事件如何向 Amazon SNS 主题发送通知。

首先,从您希望使用的 CodeCommit 库,转到设置页面,如图 7-19 所示。

图 7-19

代码提交存储库设置

触发器页签创建一个触发器,如图 7-20 所示。

图 7-20

开始代码提交触发器创建

如图 7-21 所示配置并创建触发器。对于 SNS 主题,选择出于相同目的集成到 SQS 队列中的 SNS 主题。

图 7-21

配置和创建代码提交触发器

通过 Terraform 设置组件

让我们通过 Terraform for infra structure as Code(IaC)来设置所需的 AWS 资源。

清单 7-3 显示了设置所有所需资源的示例 Terraform 代码片段。

variable "aws-account-id" {
  default = "xxxxxxxxxxxx"
}
.
.
.
provider "aws" {
  region = "${var.aws-region}"
  alias = "default"
}

data "aws_iam_policy_document" "sns-sqs-policy" {
  policy_id = "arn:aws:sqs:us-east-1:${var.aws-account-id}:testing/SQSDefaultPolicy"
  statement {
    sid = "SubscribeToSNS"
    effect = "Allow"
    principals {
      type = "AWS"
      identifiers = [ "*" ]
    }
    actions = [ "SQS:SendMessage" ]
    resources = [ "${aws_sqs_queue.main.arn}" ]
    condition {
      test = "ArnLike"
      variable = "aws:SourceArn"
      values = [ "arn:aws:sns:${var.aws-region}:${var.aws-account-id}:${var.sns-topic-prefix}*${var.sns-topic-suffix}" ]
    }
  }
}
.
.
.
resource "aws_sqs_queue" "main" {
  name = "codecommit-notifications-queue"
  delay_seconds = 90
  max_message_size = 2048
  message_retention_seconds = 86400
  receive_wait_time_seconds = 10
}

resource "aws_sqs_queue_policy" "sns" {
  queue_url = "${aws_sqs_queue.main.id}"
  policy = "${data.aws_iam_policy_document.sns-sqs-policy.json}"
}
.
.
.
output "sns-name" {
  value = "${aws_sns_topic.main.name}"
}

output "sns-arn" {
  value = "${aws_sns_topic.main.arn}"
}

Listing 7-3Setting up components with Terraform

要创建资源,请将此 Terraform 代码保存到包含。tf 扩展并初始化,如清单 7-4 所示。

  • 将清单 7-3 中的变量 repository_name 替换为您的代码提交库名称。
$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v3.59.0...
- Installed hashicorp/aws v3.59.0 (signed by HashiCorp)

Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work.

If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.

Listing 7-4Initializing Terraform

成功初始化后,所有依赖项都已下载,现在您可以运行terraform apply来部署资源。该命令的输出将类似于清单 7-5 中所示的示例片段。

$ terraform apply
provider.aws.region
  The region where AWS operations will take place. Examples
  are us-east-1, us-west-2, etc.

  Enter a value: us-east-1
.
.
.
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes
.
.
.
Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
Outputs:
sns-arn = "arn:aws:sns:us-east-1:123456789101:codecommit-target-codeommit-repository-topic"
sns-name = "codecommit-target-codeommit-repository-topic"

Listing 7-5Creating resources with Terraform

配置插件

已经设置的插件先决条件资源是 SQS 队列、SNS 主题、为 SNS 主题订阅 SQS 队列,以及设置 CodeCommit 触发器以在存储库事件时向插件 SNS 主题发送通知。现在,插件可以配置为利用已经创建的资源来完成集成。

要配置插件,进入 Jenkins 系统配置,如图 7-22 所示。

图 7-22

配置 Jenkins 系统

在系统配置页面上,可以看到 CodeCommit 插件配置。图 7-23 显示了如何开始用已经创建的 SQS 队列配置插件。

图 7-23

将 SQS 配置添加到代码提交插件

应提供 AWS 区域和 SQS 队列名称,如图 7-24 所示。该插件使用提供的 AWS 凭证测试对 SQS 队列的访问。

图 7-24

配置 SQS 队列名和 AWS 区域

如果可用,可以使用 Jenkins 上配置的现有 AWS 凭证,但是要添加新的 AWS 凭证,图 7-25 中显示了一个示例。

图 7-25

向 Jenkins 添加 AWS 凭据

  • 为插件配置的 AWS 凭据必须具有 SQS 访问权限和代码提交只读访问权限。

Jenkins CodeCommit 插件现在应该已经配置好并处于活动状态。接下来,我们将创建一个示例 Jenkins 作业来验证插件是如何工作的。

使用 AWS 代码提交源创建 Jenkins 作业

在本节中,我们将看到一个示例 Jenkins 作业如何使用 AWS CodeCommit 源代码,以及如何使用已配置的 Jenkins CodeCommit 插件进行自动构建。图 7-26 显示了如何开始创建 Jenkins 作业。

图 7-26

开始创建 Jenkins 作业

我们将创建一个 Jenkins自由式项目。如图 7-27 所示,需要提供项目名称。

图 7-27

创建 Jenkins 自由式项目

对于项目配置,需要将本章前面配置的 CodeCommit 库添加到源代码管理(SCM)中,如图 7-28 所示。

图 7-28

使用 AWS 代码提交配置 SCM

如果可用,可以使用 Jenkins 上配置的现有 CodeCommit Git 凭证,但要添加新的 Git 凭证,图 7-29 中显示了一个示例。这里提供的 Git 凭据是 CodeCommit IAM 用户的 HTTPS 凭据。

图 7-29

配置代码提交 HTTPS 凭据

为自动构建配置构建触发器,如图 7-30 所示。显示了将由插件监控的 SQS 队列。

图 7-30

设置构建触发器

对于构建,输入一些基本的示例命令,如图 7-31 所示,项目就创建好了。当一个构建被触发时,存储库的内容被克隆到 Jenkins 工作空间,图 7-31 中提供的命令列出工作空间并确认存储库内容是否被下载。

图 7-31

输入构建命令

图 7-32 中可以看到一个自由式项目的例子。

图 7-32

Jenkins 自由式项目

测试 AWS 代码提交插件

为了测试该插件,将在 CodeCommit 存储库中创建一个新的提交,这将触发 Jenkins 上的自动构建。

清单 7-6 显示了在 CodeCommit 存储库中创建一个新的提交,该存储库被配置为示例 Jenkins 作业的源。

$ touch testfile

$ git add . && git commit -m "Test listing directory"
[master fb68e27] Test listing directory
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 testfile

$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 6 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 285 bytes | 285.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
To codecommit::us-east-1://devops-ios-repository
   bc42da1..fb68e27  master -> master

Listing 7-6Adding commit to AWS CodeCommit Repository

在 Jenkins 项目上,您可以验证该项目是从新提交自动启动的,如图 7-33 所示。

图 7-33

Jenkins 作业自动构建

图 7-34 显示了包含所有构建命令输出的构建日志。

图 7-34

Jenkins 工作构建输出

摘要

Jenkins 是 DevOps 中使用非常广泛的工具,因为它具有丰富的功能,能够与许多其他工具集成以满足不同的用例,这也是它对 iOS 开发非常有用的原因。当 iOS 应用的源代码存储在 AWS CodeCommit 上时,将 CodeCommit 与 Jenkins 集成以实现端到端自动化变得至关重要。

到目前为止,我们已经深入研究了将 Jenkins 和 CodeCommit 集成到自动化 Jenkins 构建和基本构建中的过程。接下来,我们将从这里开始,向 Jenkins 添加更多特定于 iOS 的构建和测试。

八、使用 Fastlane 自动构建、测试和发布

在前一章中,我们学习了如何将存储在 AWS CodeCommit 中的应用源代码与 Jenkins jobs 集成,以便在代码发生更改时实现自动构建。拥有一个在代码更改时自动调用的构建系统是持续集成和持续交付或部署(CICD)的关键要求,因此在本章中,我们将利用自动化构建,深入探讨如何使用 Jenkins 和 Fastlane 来自动化构建、测试和发布 iOS 应用。

使用 Fastlane 匹配和亚马逊 S3 设置代码签名

iOS 开发中的代码签名是一种在 iOS 应用可以分发或上传到 app store 之前对其进行签名的机制。这是保持完整性所必需的,因为它确保 iOS 应用来自已知的可信来源,并且自上次签名以来未被修改。理想情况下,每个开发人员都有一个签名身份,但是当一个团队由多个开发人员组成,并且他们必须管理多个签名身份时,这会产生问题并增加管理开销。

有了 Fastlane 匹配,开发团队可以共享一个代码签名身份,以帮助简单的代码签名。它创建所有必需的签名资源,如证书、配置文件,并将它们存储在一个集中的位置,这样每个团队成员都可以检索这些证书并用于代码签名。当使用 Fastlane 进行应用开发和发布时,这变得无缝,因为从集中位置检索凭证和配置构建系统的过程是内置在 Fastlane 的。在持续集成和持续交付或部署(CICD)系统中使用 Fastlane 时,这一点特别有用,因为可以从集中位置自动检索凭证,并无缝构建应用。

对于代码签名凭证的集中存储,让我们看看如何将亚马逊 S3 用作 Fastlane 匹配的存储位置。在本章的后面,我们将看到如何在应用构建过程中从 S3 检索这些凭证,以便对构建工件进行签名。

正在初始化 Fastlane 匹配

必须首先在本地开发工作站上的项目文件夹中设置 Fastlane 匹配。但是首先必须在开发工作站上安装 Fastlane。安装 Fastlane 有多种方法,但最简单的方法是使用自制软件,如清单 8-1 所示。

$ brew install fastlane

Listing 8-1Installing Fastlane with Homebrew

在 Fastlane 安装之后,从 iOS 项目目录中初始化 match,如清单 8-2 所示。

对于存储模式,如清单 8-2 所示,match 支持不同的存储模式,但我们将重点使用 S3 作为存储模式,因此选择 S3。

清单 8-2。初始化匹配

  • 如果命令中出现“无法定位 Xcode”错误,请打开 Xcode 偏好设置,在位置命令行工具中,选择 Xcode CLI(命令行界面)版本,然后再次运行 Fastlane 命令。

初始化时,它在项目目录中创建一个名为 Matchfile 的文件。该文件将包含成功执行 match 所需的所有必要信息。最初,该文件不会包含所有信息,但接下来我们将配置所需的信息。

我们首先为集中式存储创建一个 S3 存储桶,并配置 AWS 凭证环境变量,允许 Fastlane 访问 S3 存储桶,如清单 8-3 所示。还配置了唯一的匹配密码;此密码用于加密/解密证书。

  • 匹配密码是用户选择的任何密码,用作额外的安全层。

记下存储桶名称、用于 AWS 凭证的环境变量名称以及匹配密码。

  • 如果没有为 AWS CLI 配置默认区域,请在 CLI 命令中使用标志--region指定 AWS 区域。
$ aws s3 mb s3://abdullahi-fastlane-certificates
$ export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxx
$ export AWS_ACCESS_KEY_ID=xxxxxxxxxxxx
$ export MATCH_PASSWORD=xxxxxxxxxxx

Listing 8-3Creating S3 bucket and configuring environment variables

使用创建的 S3 存储桶和在清单 8-3 中配置的 AWS 凭证环境变量,从清单 8-2 创建的匹配文件被定制。清单 8-4 中显示了匹配文件的示例内容。

  • 要使用此示例匹配文件,请用此内容替换您的匹配文件的内容,并将 S3 存储桶名称、应用标识符、Apple 用户名和团队 ID 更改为您的内容。
$ cat Matchfile
s3_bucket("abdullahi-fastlane-certificates")

storage_mode("s3")
s3_access_key(ENV["AWS_ACCESS_KEY_ID"])
s3_secret_access_key(ENV["AWS_SECRET_ACCESS_KEY"])

type("development") # The default type, can be: appstore, adhoc, enterprise or development

app_identifier(["com.abdullahiolaoye.sampleapplication"])
username("xxxxxxxxx@email.com") # Your Apple Developer Portal username
team_id("XXXXXXXXXX") # Your team ID

# For all available options run `fastlane match --help`
# Remove the # in the beginning of the line to enable the other options

# The docs are available on https://docs.fastlane.tools/actions/match

Listing 8-4New configured Matchfile

如清单 8-4 所示,除了 S3 bucket name 和 AWS credentials 环境变量,app identifier、Apple developer username 和 team ID 也在 Matchfile 中配置。

在亚马逊 S3 存储证书和密钥

配置好匹配文件后,现在我们可以生成证书并存储在集中式 S3 存储桶中。清单 8-5 展示了如何为开发和示例输出生成证书的示例。清单 8-5 中的命令生成了很多输出,所以只显示了一个片段。

  • 该命令必须从存储匹配文件的项目目录中执行。

  • 清单 8-5 中的命令需要用户输入,例如 Apple ID 密码和钥匙串密码。

清单 8-5。Fastlane 生成发展凭证

当该命令完成时,签名凭证将被存储在上述 S3 桶中,如图 8-1 所示。

图 8-1

每个团队 ID 的代码签名凭证存储在 S3 存储桶中

签名凭证由团队 ID 组织,在每个团队 ID 文件夹中,签名凭证的存储如图 8-2 所示。

图 8-2

特定团队 ID 的签名凭据

在 AWS 机密管理器中存储匹配机密和参数

如前所述,使用 Fastlane 匹配进行代码签名的主要好处是易于跨不同的开发人员和构建系统重用一个签名凭据。现在,签名凭证存储在一个集中的 S3 存储桶中,用于正确访问和使用这些存储的代码签名凭证的凭证也必须存储在一个集中的位置,以便在需要时可以方便地检索它们。

到目前为止,这些签名凭证的其他用户将需要的凭证是访问集中式 S3 桶的 AWS 凭证和解密代码签名凭证的匹配密码,所有这些都在清单 8-3 中进行了配置。应该存储的附加信息是 S3 桶名应用标识符苹果用户名团队 ID

为了存储这些内容,我们将使用 AWS Secrets Manager,这是一个专为存储机密而设计的 AWS 服务。图 8-3 显示了如何在 AWS Secrets Manager 中创建一个秘密来存储这些秘密。

图 8-3

创建 AWS 机密管理器机密来存储 Fastlane 机密

在秘密创建之后,它应该在秘密列表上可见。图 8-4 显示了一次成功的秘密创建。

图 8-4

验证秘密创建

接下来,我存储秘密,它应该是可见的,如图 8-5 所示。现在,作为构建过程的一部分,可以手动或以编程方式检索秘密。

图 8-5

AWS 机密管理器中存储的所有机密和参数

  • 图 8-5 中使用的密钥是示例,可以定制成适合您的密钥名称。在后面的部分中,我将展示这些密钥在构建脚本中用于自动秘密检索的地方。

设置 Jenkins 环境

要使用 Jenkins 和 Fastlane 构建和发布 iOS 应用,需要在 Jenkins 环境中安装一些工具。本节将验证所需的工具。

设置和验证 Xcode 安装

对于任何 iOS 应用版本,都必须安装 Xcode。从 App Store 安装 Xcode 时,它也会安装 Fastlane 使用的命令行界面(CLI)工具。

Xcode 安装后,确保接受许可协议并验证 Xcode 已成功启动,如图 8-6 所示。

图 8-6

验证 Xcode 安装

还要验证 Xcode 命令行工具是否如清单 8-6 所示安装。

$ xcode-select --version
xcode-select --version
xcode-select version 2384.

$ xcodebuild -version
xcodebuild -version
Xcode 13.0
Build version 13A233

$ xcodebuild

Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild

User defaults from command line:
    IDEPackageSupportUseBuiltinSCM = YES

xcodebuild: error: The directory /Users/userA does not contain an Xcode project.

Listing 8-6Verifying Xcode CLI tools

验证 Fastlane 安装

验证 Fastlane 是否安装在 Jenkins 环境中,如清单 8-7 所示。

清单 8-7。验证 Fastlane 安装

设置 AWS CLI

在 Jenkins 构建期间,AWS CLI 将用于检索存储在 AWS Secret Manager 中的所有 Fastlane 机密,因此需要在 Jenkins 环境中安装和配置 AWS CLI。

AWS CLI 可以按照清单 8-8 中所示进行验证和配置。

$ aws –-version
$ aws configure

Listing 8-8Verifying and configuring AWS CLI

安装 JSON 查询语言(jq)

当从 AWS Secrets Manager 中检索机密时,它们以 JSON 的形式返回,并且需要被解析以检索相关的字符串。对于解析,使用 jq,因此它应该安装在 Jenkins 环境中。可以用自制软件安装,如清单 8-9 所示。

$ brew install jq

Listing 8-9Verifying jq installation

用 Fastlane 自动化测试和构建

在这一节中,我们将重点介绍如何与 Fastlane 和 Jenkins 一起自动测试和构建 iOS 应用。

将通道添加到快速文件

首先要将 Fastlane 添加到 iOS 应用项目中,应该在 iOS 项目的根文件夹中创建一个 fastlane 目录,并在 Fastlane 文件夹中创建一个名为 Fastfile 的文件,如清单 8-10 所示。

$ mkdir fastlane
$ cd fastlane && touch Fastfile

Listing 8-10Creating Fastlane directory and Fastfile from project root folder

Fastfile 是用 Ruby 编写的,包含了 Fastlane 在 iOS 应用上执行操作所需的所有指令。快速文件中的指令写在通道中。通道包含在 iOS 应用上执行特定操作的所有逻辑,当调用一组特定的指令时,通道的名称被传递给 Fastlane 命令。

清单 8-11 中显示了可以添加到清单 8-10 中新创建的 Fastfile 中的测试和构建示例通道。

lane :build do
    match(
      type: "appstore",
      storage_mode: "s3",
      s3_bucket: ENV["S3_BUCKET"],
      s3_access_key: ENV["AWS_ACCESS_KEY_ID"],
      s3_secret_access_key: ENV["AWS_SECRET_ACCESS_KEY"],
      app_identifier: ENV["APP_IDENTIFIER"],
      username: ENV["APPLE_DEVELOPER_USERNAME"],
      team_id: ENV["TEAM_ID"]
    )
    increment_build_number(build_number: ENV["BUILD_ID"])
    gym(project: "SampleApp.xcodeproj")
  end

lane :test do
    scan(project: "SampleApp.xcodeproj",
              devices: ["iPhone Xs"])
  end

Listing 8-11Adding Fastlane lanes for test and build to Fastfile

如图所示,有两条车道,即测试建造。在通道配置中,存储在 AWS Secrets Manager 中的所有参数都将被检索,并在构建时通过环境变量提供给 Fastlane。

配置 Jenkins 项目

在前一章中,Jenkins 项目已经建立并与 AWS CodeCommit 集成,用于自动构建。该项目将被扩展,以将 iOS 构建和测试逻辑添加到其构建配置中。在清单 8-12 中可以看到一个示例构建脚本。

set +x
echo "Set fastlane variables..."
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

echo "Retrieving Secrets from AWS Secret Manager..."
ACCESS_KEY_ID=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .AWS_ACCESS_KEY_ID`
SECRET_ACCESS_KEY=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .AWS_SECRET_ACCESS_KEY`
MATCH_PASSWORD=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .MATCH_PASSWORD`
S3_BUCKET=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .S3_BUCKET`
APP_IDENTIFIER=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .APP_IDENTIFIER`
APPLE_DEVELOPER_USERNAME=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .APPLE_DEVELOPER_USERNAME`
TEAM_ID=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .TEAM_ID`

echo "Setting fastlane match environment variables..."
export AWS_ACCESS_KEY_ID=$ACCESS_KEY_ID && export AWS_SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY && export MATCH_PASSWORD=$MATCH_PASSWORD && export S3_BUCKET=$S3_BUCKET && export APP_IDENTIFIER=$APP_IDENTIFIER && export APPLE_DEVELOPER_USERNAME=$APPLE_DEVELOPER_USERNAME && export TEAM_ID=$TEAM_ID

echo "Starting Fastlane..."
fastlane test
fastlane build

Listing 8-12Example test and build script

如清单 8-12 所示,首先从 AWS Secret Manager 中检索参数并配置为环境变量,然后调用测试和构建通道来测试和构建 iOS 应用。该脚本被添加到 Jenkins 中以覆盖现有的构建脚本,如图 8-7 所示。

图 8-7

Jenkins 构建配置

触发 Jenkins 项目

将 Fastlane 构建和测试通道添加到 iOS 项目中,并相应地配置 Jenkins 构建,然后可以在 AWS CodeCommit 中创建新的提交,以开始新的构建。代码可以被提交和推送,如清单 8-13 所示。

$ git add . && git commit -m "Build and test app"
[master ea9e896] Build and test app
 1 file changed, 1 insertion(+), 33 deletions(-)

$ git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 6 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 368 bytes | 368.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
To codecommit::us-east-1://devops-ios-repository
   fb68e27..ea9e896  master -> master

Listing 8-13Committing and pushing changes to AWS CodeCommit

这开始了对 Jenkins 的构建,如图 8-8 所示。

图 8-8

开始 iOS 应用测试和构建的新承诺

在 Jenkins 中可以看到构建日志,但是清单 8-14 中显示了构建触发的日志片段。

清单 8-14。Fastlane 测试并构建 Jenkins 日志片段

  • Jenkins 必须能够找到所需的安装工具,如 awsjq 。如果您得到诸如“jq: command not found”或“aws: command not found”之类的构建错误,请适当地配置 Jenkins PATH 变量或指定完整路径,其中包括构建脚本中的安装目录,例如/usr/local/bin/aws。

自动发布到 App Store Connect

App Store Connect 允许您管理您的 iOS 应用。从那里,用户可以使用 TestFlight 分发 iOS 应用进行测试,并将应用发布到应用商店。要在 App Store Connect 上管理 iOS 应用,首先要将构建的应用上传到 App Store Connect 门户,然后在那里进行管理。

Fastlane 还自动将 iOS 应用发布到 App Store Connect。在本节中,我们将扩展在上一节中配置的 Jenkins 项目,该项目测试并构建应用,以添加一个将构建的应用发布到 App Store Connect 的操作。

我们将调查 App Store Connect 的两个用例,发布一个应用到 TestFlight 进行 beta 测试,发布一个应用将提交到 App Store。

设置 App Store 连接 API 密钥

为了让 Fastlane 在没有人工干预的情况下以编程方式与 App Store Connect 进行交互,将生成一个 App Store Connect API 密钥来认证 Fastlane。要生成 API 密匙,你从 App Store Connect 仪表盘开始,访问用户,进入页面,如图 8-9 所示。

图 8-9

App Store 连接仪表板

此页面列出了此 Apple developer 帐户的所有用户及其角色。如图 8-10 所示,切换到选项卡。

图 8-10

从“用户和访问”页面访问“密钥”选项卡

如果这是第一次为 App Store Connect API 生成 API key,必须先请求访问,如图 8-11 所示。

图 8-11

请求访问 App Store 连接 API

一旦访问请求被批准(通常是立即批准),就可以生成一个 API 密钥,如图 8-12 所示。

图 8-12

正在生成 App Store 连接 API 密钥

提供 API 密钥的名称和访问级别。示例如图 8-13 所示。

图 8-13

提供 API 键名并生成它

API 密钥生成后,就可以下载了。下载 API 密钥,如图 8-14 所示。

图 8-14

正在下载 API 密钥

  • 此密钥只能下载一次,因此应该存储在安全的位置。如果丢失了,必须重新生成。

下载 API 密钥后,下载选项不再可用,如图 8-15 所示。

图 8-15

下载 API 密钥选项不可用

API 密钥下载在 p8 扩展文件中。要在后续步骤中使用 API 密钥,它应该是 base64 编码的,如清单 8-15 所示。

$ base64 AuthKey_AxxxxxxxBY.p8 > base64output.txt

Listing 8-15Base64 encode App Store Connect API Key

除了下载和 base64 编码的 API 密钥之外,发行者 ID密钥 ID 也应该被检索并存储在一个安全的位置。

在 AWS Secret Manager 中存储机密

从 App Store Connect 门户检索到的所有机密都将被构建过程使用,因此需要将这些机密存储在一个集中的安全位置,以便在构建时可以检索到它们。

对于这个用例,AWS Secrets Manager 将用于存储 App Store Connect secrets,类似于它用于存储 Fastlane 机密和参数的方式。如图 8-16 所示,创建一个新的秘密。

图 8-16

创建机密以存储 App Store 连接机密

然后如图 8-17 所示存储秘密。base64 编码的 API 密钥存储为带有密钥 API_KEY 的值。从 App Store Connect 门户检索的密钥 ID 和发行者 ID 分别存储为带有密钥 KEY_IDApp _ Store _ Connect _ ISSUER _ ID的值。

图 8-17

存储 App Store 连接机密

试飞放行

TestFlight 允许 iOS 开发者邀请真实用户测试应用,以便在应用商店公开发布之前收集反馈。要使用 TestFlight,需要构建应用并发布到 App Store Connect。在这里,我们将看到如何应用发布到试飞可以自动与 Fastlane。

将试飞通道添加到快速文件

扩展之前创建的配置了测试和构建通道的 Fastfile,可以添加一个测试飞行通道。清单 8-16 显示了试飞的一个示例通道配置。

lane :testflight do
  api_key = app_store_connect_api_key(
    key_id: ENV["KEY_ID"],
    issuer_id: ENV["APP_STORE_CONNECT_ISSUER_ID"],
    key_content: ENV["API_KEY"],
    duration: 1200,
    in_house: false,
    is_key_content_base64: true,
  )

  pilot(
    api_key: api_key,
 )
  End

Listing 8-16Fastlane lane for TestFlight release

如清单 8-16 所示,密钥 ID发行者 IDAPI 密钥将从 AWS Secrets Manager 中检索,并通过环境变量提供,供构建流程在运行时使用 Fastlane。

配置 Jenkins 项目

根据清单 8-12 配置的 Jenkins 构建脚本应该被修改以添加新的试飞车道,如清单 8-17 所示。

set +x
echo "Set fastlane variables..."
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

echo "Retrieving Secrets from AWS Secret Manager..."
ACCESS_KEY_ID=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .AWS_ACCESS_KEY_ID`
SECRET_ACCESS_KEY=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .AWS_SECRET_ACCESS_KEY`
MATCH_PASSWORD=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .MATCH_PASSWORD`
S3_BUCKET=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .S3_BUCKET`
APP_IDENTIFIER=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .APP_IDENTIFIER`
APPLE_DEVELOPER_USERNAME=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .APPLE_DEVELOPER_USERNAME`
TEAM_ID=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString  --output text | jq -r .TEAM_ID`
APP_STORE_CONNECT_ISSUER_ID=`aws secretsmanager get-secret-value --secret-id app-store-connect-secret --query SecretString --output text | jq -r .APP_STORE_CONNECT_ISSUER_ID`

KEY_ID=`aws secretsmanager get-secret-value --secret-id app-store-connect-secret --query SecretString --output text | jq -r .KEY_ID`
API_KEY=`aws secretsmanager get-secret-value --secret-id app-store-connect-secret --query SecretString --output text | jq -r .API_KEY`

echo "Setting fastlane match environment variables..."
export AWS_ACCESS_KEY_ID=$ACCESS_KEY_ID && export AWS_SECRET_ACCESS_KEY=$SECRET_ACCESS_KEY && export MATCH_PASSWORD=$MATCH_PASSWORD && export S3_BUCKET=$S3_BUCKET && export APP_IDENTIFIER=$APP_IDENTIFIER && export APPLE_DEVELOPER_USERNAME=$APPLE_DEVELOPER_USERNAME && export TEAM_ID=$TEAM_ID

echo "Setting app store connect secret environemnt variables"
export APP_STORE_CONNECT_ISSUER_ID=$APP_STORE_CONNECT_ISSUER_ID && export KEY_ID=$KEY_ID && export API_KEY=$API_KEY

echo "Starting Fastlane..."
fastlane test
fastlane build
fastlane testflight

Listing 8-17Adding TestFlight to Jenkins build script

存储在 AWS Secrets Manager 中的 App Store Connect secrets 将被检索,并在调用 testflight lane 之前设置为环境变量。

触发 Jenkins 项目

TestFlight lane 已经添加到应用源代码 Fastfile 中,Jenkins 项目也相应地进行了修改,现在可以通过在 AWS CodeCommit 中创建新的 commit 来触发 Jenkins 项目,如清单 8-18 所示。

$ git add . && git commit -m "Upload to testflight"
[master 3a1febb] Upload to testflight
 1 file changed, 17 insertions(+), 1 deletion(-)

$ git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 6 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 580 bytes | 580.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
To codecommit::us-east-1://devops-ios-repository
   ea9e896..3a1febb  master -> master

Listing 8-18Creating a new commit in CodeCommit for TestFlight

新提交在 Jenkins 上可见,如图 8-18 所示。

图 8-18

触发试飞发布的新提交

清单 8-19 中显示了触发构建的日志片段。

清单 8-19。试飞上传的 Jenkins 日志片段

从 App Store Connect 上的 TestFlight 控制台,可以看到刚刚上传的构建,如图 8-19 所示。

图 8-19

Fastlane 试飞上传

自动发布到应用商店

如果要将应用上传到 App Store Connect 进行 App Store 提交,此过程也可以由 Fastlane 自动完成。

将 App Store Lane 添加到 Fastfile

App Store 的 lane 配置也应该添加到前面操作中使用的同一个 Fastfile 中。清单 8-20 显示了应用商店上传的通道配置示例。

lane :appstore do
  api_key = app_store_connect_api_key(
    key_id: ENV["KEY_ID"],
    issuer_id: ENV["APP_STORE_CONNECT_ISSUER_ID"],
    key_content: ENV["API_KEY"],
    duration: 1200,
    in_house: false,
    is_key_content_base64: true,
  )

  deliver(
    api_key: api_key,
    force: true,
    run_precheck_before_submit: false
  )
  End

Listing 8-20App Store lane configuration

类似地,对于其他通道配置,从构建时环境变量中检索凭证。

配置 Jenkins 项目

App Store 上传的 Jenkins 构建配置与 TestFlight 构建非常相似,因为两者都需要上传到 App Store Connect。唯一的区别是appstore通道是由 Fastlane 调用的,而不是由testflight通道调用的,如清单 8-17 所示。清单 8-21 显示了清单 8-17 中定义的构建脚本的 Fastlane 部分,并显示了应该对构建脚本进行的微小更改。

echo "Starting Fastlane..."
fastlane test
fastlane build
fastlane appstore

Listing 8-21Minor changes required for App Store lane

触发 Jenkins 项目

将 appstore lane 添加到 Fastfile 并相应地配置 Jenkins 构建脚本后,可以在 CodeCommit 中创建新的提交,如清单 8-22 所示。

$ git add . && git commit -m "Upload to appstore"
[master 83fa283] Upload to appstore
 1 file changed, 13 insertions(+), 13 deletions(-)

$ git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 6 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 469 bytes | 469.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
To codecommit::us-east-1://devops-ios-repository
   0f80b39..83fa283  master -> master

Listing 8-22Creating new commit for App Store upload

这开始了对 Jenkins 的构建;清单 8-23 显示了 App Store 上传的构建日志片段。

清单 8-23。应用商店上传的 Jenkins 日志片段

上传的 build 在 App Store Connect 上可见,如图 8-20 所示。

图 8-20

为 App Store 版本上传的版本

摘要

Fastlane 是一个强大的工具,有助于自动完成 iOS 应用开发中的许多手动任务,将该工具与 Jenkins 集成在一起开辟了更多的自动化可能性。在本章中,我们探讨了其中的一些可能性,并研究了如何使用 Jenkins 自动构建来自动测试、构建和发布 iOS 应用到 App Store Connect。

本章介绍的 Fastlane 测试使用 iOS 模拟器进行测试。接下来,我们将深入使用 AWS Device Farm 在真实设备上测试 AWS 云上的 iOS 应用。

九、将 AWS 设备群用于测试

当在 iOS 模拟器上测试 iOS 应用时,您可以测试应用的功能和行为,但模拟器并不完全像真实的硬件设备一样工作,因此应用在模拟器上可能工作正常,但安装在真实的 iOS 设备上时表现不同。开发期间在真实的移动设备上测试 iOS 应用可以提高应用的质量,因为您可以模拟真实用户将如何与应用交互。

在这一章中,我们将探讨如何在 AWS Device Farm 上测试真实移动设备上的应用,并将 AWS Device Farm 与 Jenkins 集成,以自动化开发和测试流程。

AWS 设备群简介

AWS Device Farm 是一项服务,用于在 AWS 云上托管的真实物理设备(如手机和平板电脑)上测试 iOS、Android 和 web 应用并与之交互。通过 Device Farm,您可以使用各种支持的测试框架为您的应用设置自动化测试,并设置对设备的远程访问,您可以在其中安装应用并与应用实时交互。然而,我们将关注 AWS 设备群的自动化测试特性。

AWS Device Farm 有一些术语,我们在研究该服务时会用到。以下是其中一些术语及其含义:

  • 测试–一个单独的测试用例。

  • 套件(Suite)——组织在测试包中的一组测试,包含一个或多个测试。

  • 工作–用一个或多个套件对单个设备测试单个应用。

  • 运行–在一组设备上运行一组测试的应用的特定版本。一次运行由一个或多个作业组成。

  • 项目–包含运行的逻辑工作空间。每次运行都是针对一个或多个设备对一个应用进行测试。

  • 设备池–具有相似特征的设备集合

要在 AWS Device Farm 上测试 iOS 应用,您需要提供从应用构建中生成的 ipa 应用包,还需要提供您的测试用例或使用内置测试框架,选择用于测试的物理设备,并配置将在其上测试应用的设备状态。测试后,AWS 设备群生成报告;该报告的一些组成部分包括

  • 通过和失败信息

  • 事故报告

  • 测试和设备日志

  • 截屏

  • 工作特性

这些报告将在 AWS 设备群中保留 400 天。

为应用测试生成 ipa 包

要在 AWS 设备场上安排测试运行,需要一个可测试的 iOS 应用归档文件(ipa ),用于测试的 ipa 必须是专门为测试而构建的。

可以从 Xcode 生成测试应用包。可以构建一个应用进行测试,如图 9-1 所示。

图 9-1

构建用于测试的 iOS 应用

构建完成后,会生成一个应用文件,可以导出并用于测试。图 9-2 显示了如何访问存储生成的应用档案的目录位置。

图 9-2

打开生成项目位置

应用档案(带有。app 扩展)应如图 9-3 所示进行检索。

图 9-3

正在检索应用档案以进行测试

可以从图 9-3 中检索的应用档案中创建一个 ipa 档案用于设备群测试,如清单 9-1 所示。

  • 清单 9-1 中的命令必须从图 9-3 所示的 Debug-iphoneos 目录中执行。

    $ mkdir Payload && cp -r SampleApp.app Payload/
    $ zip -r Payload.zip Payload && mv Payload.zip SampleApp.ipa
    
    Listing 9-1Generating ipa for Device Farm testing
    
    

如清单 9-1 所示,创建一个负载目录,应用文件被复制到该目录中。然后,该目录被归档并使用 ipa 扩展名重命名。

设置设备场项目并安排测试运行

使用为设备群测试生成的应用 ipa 文件,我们将探索如何通过 AWS 管理控制台和 AWS CLI 来安排 AWS 设备群的测试运行。

使用 AWS 控制台安排测试运行

如图 9-4 所示,可以从 AWS 管理控制台访问 AWS 设备群控制台。

图 9-4

访问 AWS 设备场控制台

  • AWS 设备群目前仅在美国西部-2 AWS 地区可用。

AWS 设备场中的测试在项目中运行;可以使用现有项目,也可以创建新项目,如图 9-5 所示。

图 9-5

创建设备场项目

AWS Device Farm 支持多种测试框架和内置测试类型。目前对于 iOS,Device Farm 支持以下测试框架:

  • 阿皮亚姆

  • 葫芦

  • UI 自动化

  • XCTest

  • XCTest UI

对于不需要您编写或维护测试脚本的内置测试类型,它提供了内置模糊

我们将探索如何使用提供的内置模糊测试和 XCTest UI 测试框架在 AWS 设备群中运行测试。

运行内置模糊测试

内置模糊测试随机向设备发送用户界面事件,然后报告结果。从一个设备群项目中,可以创建一个自动化的测试运行,如图 9-6 所示。

图 9-6

创建自动化测试运行

可以上传应用 ipa 档案,如图 9-7 所示。

图 9-7

上传应用 ipa

应用上传后,会显示应用的一些详细信息,也可以配置运行的名称,如图 9-8 所示。

图 9-8

配置运行名称

  • 默认情况下,运行名称设置为上传的 ipa 应用的名称。这个名字可以改。

接下来,我们通过选择要使用的测试框架的类型来配置测试。图 9-9 显示了从可用选项中选择内置模糊框架。所有默认的模糊配置都可以保持原样。

图 9-9

选择内置模糊测试框架

在提供应用归档和配置测试框架之后,您可以选择测试应用的物理设备的类型。如图 9-10 所示,您可以使用已配置的设备池或创建自己的定制设备池。图 9-10 中使用的设备池是顶级设备;还显示提供的 app 只兼容这两款设备。

图 9-10

选择设备池

您还可以配置设备状态。设备状态配置允许您选择设备语言,并配置网络选项,如 Wi-Fi、蓝牙、GPS 等。,适用于依赖这些设备功能的应用。这些是这个示例应用的默认设置,如图 9-11 所示。

图 9-11

查看设备状态配置并开始运行

一旦开始运行,它就进入挂起状态。运行开始需要几分钟时间,具体取决于物理设备的可用性。

要查看更多详细信息并监控设备池中每个设备上运行的测试,您可以选择该测试,运行详细信息将显示出来,如图 9-12 所示。

图 9-12

挂起状态下运行的详细信息

运行完成后,可以查看运行的状态。显示执行的测试数量及其不同的状态。饼图还显示了百分比通过和其他状态(如果适用),如图 9-13 所示。

图 9-13

运行的测试状态

要查看设备池中特定设备的测试报告详细信息,请选择该设备。从图 9-13 可以查看 iPhone 11 和 iPhone XR 的报告。在图 9-14 中可以看到 iPhone 11 的示例报告。

图 9-14

iPhone 11 的测试报告

运行 XCTest UI 测试

XCTest UI 框架允许您测试应用的 UI 功能。当您构建项目进行测试时,Xcode 会生成测试包。要在 Device Farm 上使用 XCTest UI 框架,可以使用从清单 9-1 中生成的相同应用包,但是必须检索测试包并将其格式化为 ipa 文件,如下所示。

为 XCTest UI 生成测试包

测试包保存在与构建工件相同的位置,可以如图 9-2 所示进行访问。测试包的命名模式为UITests-runner . App,可以检索图 9-1 中样本的测试包,如图 9-15 所示。

图 9-15

正在检索用于测试的 XCTests UI 包

可以从图 9-15 中检索的测试捆绑包中创建 ipa 档案,以实现设备群兼容性,如清单 9-2 所示。

$ mkdir Payload && cp -r SampleAppUITests-Runner.app Payload/
$ zip -r Payload.zip Payload && mv Payload.zip XCTestUI.ipa

Listing 9-2Generating ipa for Device Farm testing

与前面生成的应用构建 ipa 一样,在清单 9-2 中,创建了一个有效负载目录,并将测试包复制到该目录中。然后,该目录被归档并使用 ipa 扩展名重命名。

上传应用和测试包

要开始另一个测试运行,可以如图 9-6 所示开始创建测试运行,如图 9-7 所示上传 app ipa 包。可以修改默认的测试运行名称,如图 9-16 所示。

图 9-16

自定义测试运行名称

对于测试框架,应该从选项中选择 XCTest UI。一旦选择了测试类型,上传从清单 9-2 创建的测试 ipa 包的选项也会出现,如图 9-17 所示。

图 9-17

选择测试框架并上传测试包

一旦测试包被上传,选择测试的执行环境。应选择一个定制环境,YAML 测试规范可如图 9-18 所示进行配置。

图 9-18

配置执行环境和测试规范

测试规范包含了不同的阶段和将被执行来执行这个测试的命令。默认的 YAML 规范可以原样使用,但也可以修改它以添加自定义命令。

创建自定义设备池

下一步是选择一个设备池来运行测试。在图 9-10 中,一个受管理的设备池被用于运行测试,但是让我们探索一下如何创建一个定制的设备池。通过创建自定义设备池,您可以控制选择要在其上运行测试的确切设备。

可以创建一个设备池,如图 9-19 所示。

图 9-19

创建自定义设备池

创建自定义设备池包括为设备池提供一个名称,并选择应该在池中的移动设备。图 9-20 显示了一个只有一个设备的静态设备池创建示例,即 iOS 14.6 的苹果 iPhone X。使用动态设备池,您可以创建规则,以便将符合规则的设备添加到您的设备池中。

图 9-20

使用苹果 iPhone X 的自定义设备池

运行测试

可以选择创建的自定义设备池进行测试,如图 9-21 所示。

图 9-21

选择自定义设备池

如图 9-21 所示,该设备池中只有一个设备,并且该设备与正在测试的应用兼容。其余的配置可以保留为默认,如图 9-11 所示开始运行。一旦创建了试运行,就可以像图 9-12 一样监控其状态。图 9-22 显示了一个完成的 XCTest UI 测试的例子。

图 9-22

已完成 XCTest UI 测试

使用 AWS CLI 计划测试运行

正如 AWS 控制台所示,首先创建一个设备场项目。创建一个项目和示例输出如清单 9-3 所示。

$ aws devicefarm create-project --name SampleApp2 --region us-west-2
{
    "project": {
        "arn": "arn:aws:devicefarm:us-west-2:123456789101:project:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd",
        "name": "SampleApp2",
        "created": "2090-20-20T16:25:11.049000+00:00"
    }
}

Listing 9-3Creating Device Farm project with AWS CLI

用 AWS CLI 创建的项目也可以在 AWS 控制台上看到,如图 9-23 所示。

图 9-23

在 AWS 控制台上查看使用 CLI 创建的项目

  • 该命令返回的 Amazon 资源名称(ARN)应该被存储,并将在该项目的后续 CLI 命令中使用。

通过 AWS CLI 将应用上传到 AWS 设备群的过程分为两个步骤。首先创建一个上传,这将生成一个 S3 预先指定的 URL,文件将被上传到这个 URL。清单 9-4 显示了如何为清单 9-3 中创建的项目创建一个上传,如图 9-23 所示。

  • 将从命令返回的上传 ARN 存储在 arn 部分,如下所示。它将在针对此上传的后续 CLI 命令中使用。
$ aws devicefarm create-upload --project-arn arn:aws:devicefarm:us-west-2:123456789101:project:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd --name SampleApp.ipa --type IOS_APP --region us-west-2
{
    "upload": {
        "arn": "arn:aws:devicefarm:us-west-2:123456789101:upload:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a993d0ffd4f8",
        "name": "SampleApp.ipa",
        "created": "2090-20-20T16:33:23.578000+00:00",
        "type": "IOS_APP",
        "status": "INITIALIZED",
        "url": "https://prod-us-west-2-uploads.s3-us-west-2.amazonaws.com/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A123456789101%3Aproject%3Aabcdefg2-46a7-4ebf-b3ab-7de683ad43cd/uploads/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A123456789101%3Aupload%3Aabcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a36575959ffd4f8/SampleApp.ipa?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211017T163323Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86400&X-Amz-Credential=AKIAUJHLTYS5AWNTRO6L%2F20211017%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=4758748956745646fhfgh68768984292",
        "category": "PRIVATE"
    }
}

Listing 9-4Creating an upload for project and output

然后可以将应用上传到创建上传时返回的 S3 签名的 URL,如清单 9-5 所示。

$ curl -T SampleApp.ipa https://prod-us-west-2-uploads.s3-us-west-2.amazonaws.com/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A123456789101%3Aproject%3Aabcdefg2-46a7-4ebf-b3ab-7de683ad43cd/uploads/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A123456789101%3Aupload%3Aabcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a36575959ffd4f8/SampleApp.ipa?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211017T163323Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86400&X-Amz-Credential=AKIAUJHLTYS5AWNTRO6L%2F20211017%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=4758748956745646fhfgh68768984292

Listing 9-5Uploading application archive

可以使用 AWS CLI 检索上传的状态,如清单 9-6 所示。在使用该应用安排运行之前,状态必须为成功。

  • 可以检索在--arn参数中传递的上传 ARN,如清单 9-4 所示。
$ aws devicefarm get-upload --arn arn:aws:devicefarm:us-west-2:123456789101:upload:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a993d0ffd4f8 --region us-west-2
{
    "upload": {
        "arn": "arn:aws:devicefarm:us-west-2:123456789101:upload:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a993d0ffd4f8",
        "name": "SampleApp.ipa",
        "created": "2090-20-20T16:33:23.578000+00:00",
        "type": "IOS_APP

",
        "status": "SUCCEEDED",
        "url": "https://prod-us-west-2-uploads.s3-us-west-2.amazonaws.com/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A123456789101%3Aproject%3Aabcdefg2-46a7-4ebf-b3ab-7de683ad43cd/uploads/arn%3Aaws%3Adevicefarm%3Aus-west-2%3A123456789101%3Aupload%3Aabcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a993d0ffd4f8/SampleApp.ipa?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211017T163908Z&X-Amz-SignedHeaders=host&X-Amz-Expires=86400&X-Amz-Credential=AKIAUJHLTYS5AWNTRO6L%2F20211017%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=02d8120348419a7007602011f6786c80f53e930ce63c9f6ade13c43e41453530",
        "metadata": "{\"activity_name\":\"\",\"minimum_arm\":6,\"error_type\":null,\"package_name\":\"com.abdullahiolaoye.sampleapplication\",\"sdk_version\":1400,\"files\":{},\"warning_type\":null,\"supported_os\":\"14.0\",\"executable\":\"SampleApp\",\"platform\":[\"iPhoneOS\"],\"form_factor\":[1,2]}",
        "category": "PRIVATE"
    }

}

Listing 9-6Checking upload status

在安排运行之前,需要的一个资源是设备池。要使用内置的设备池,您可以使用 AWS CLI 查看项目可用的设备池,如清单 9-7 所示。

$ aws devicefarm list-device-pools --arn arn:aws:devicefarm:us-west-2:123456789101:project:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd --region us-west-2
{
    "devicePools": [
        {
            "arn": "arn:aws:devicefarm:us-west-2::devicepool:082d10e5-d7d7-48a5-ba5c-b33d66efa1f5",
            "name": "Top Devices",
            "description": "Top devices",
            "type": "CURATED",
            "rules": [
                {
                    "attribute": "ARN",
                    "operator": "IN",
                    "value": "[\"arn:aws:devicefarm:us-west-2::device:CE68825ABE5A4740B56F10111FD47844\",\"arn:aws:devicefarm:us-west-2::device:692AE103025C4C8B8682D22556957C83\",\"arn:aws:devicefarm:us-west-2::device:2CC987870E204BB18E7E36EF5F3C3F45\",\"arn:aws:devicefarm:us-west-2::device:8766BD1DD11744B0ACEA337A6D9BEBEF\",\"arn:aws:devicefarm:us-west-2::device:1F7E40CA59B6467F9443943E14F93848\",\"arn:aws:devicefarm:us-west-2::device:8B4E8F953E0F4460BBC2A18A504D8FC2\",\"arn:aws:devicefarm:us-west-2::device:23E8A18A1966455A8DC1E2ABF8A07F05\",\"arn:aws:devicefarm:us-west-2::device:19B1FD045303482BAE75EE14AFC29AA5\",\"arn:aws:devicefarm:us-west-2::device:57D25EA0789643648E8B4F922B9559AB\",\"arn:aws:devicefarm:us-west-2::device:2330880C98CE4AD287D354F6A58F8450\"]"
                }

            ]
        },
        {
            "arn": "arn:aws:devicefarm:us-west-2::devicepool:1c59cfd0-ee56-4443-b290-7a808d9fd885",
            "name": "Web Performance",
            "type": "CURATED",
            "rules": [
                {
                    "attribute": "ARN",
                    "operator": "IN",
                    "value": "[\"arn:aws:devicefarm:us-west-2::device:2832D5722BEF4FF2B04498ECC4C1C2F6\",\"arn:aws:devicefarm:us-west-2::device:4F74D943F7594EFF96957E238B3CA131\",\"arn:aws:devicefarm:us-west-2::device:5F20BBED05F74D6288D51236B0FB9895\",\"arn:aws:devicefarm:us-west-2::device:1F7E40CA59B6467F9443943E14F93848\",\"arn:aws:devicefarm:us-west-2::device:A7CCFD183C314CE2B44B0BB284AAEA0A\"]"
                }
            ]
        }
    ]
}

Listing 9-7Showing available device pools and output snippet

该命令输出返回设备池及其 Amazon 资源名称(ARN)的列表。

  • 存储设备池的 ARN 以用于计划运行。要使用内置的“Top Devices”池,请存储该设备池的 ARN,如清单 9-7 中所示的命令输出所示。

现在,安排运行所需的所有资源都已配置完毕。可以使用 AWS CLI 使用内置的 Fuzz 测试类型来安排测试运行,如清单 9-8 所示。

$ aws devicefarm schedule-run --project-arn arn:aws:devicefarm:us-west-2:123456789101:project:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd --app-arn arn:aws:devicefarm:us-west-2:123456789101:upload:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a993d0ffd4f8 --device-pool-arn arn:aws:devicefarm:us-west-2::devicepool:082d10e5-d7d7-48a5-ba5c-b33d66efa1f5 --name SampleApp2.ipa --test type=BUILTIN_FUZZ --region us-west-2
{
    "run": {
        "arn": "arn:aws:devicefarm:us-west-2:123456789101:run:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/4f324434-2652-45f3-b065-9961e235cfd4",
        "name": "SampleApp2.ipa",
        "type": "BUILTIN_FUZZ",
        "platform": "IOS_APP",
        "created": "2090-20-20T16:45:02.097000+00:00",
        "status": "SCHEDULING",
        "result": "PENDING",
        "started": "2090-20-20T16:45:02.097000+00:00",
        "counters": {
            "total": 0,
            "passed": 0,
            "failed": 0,
            "warned": 0,
            "errored": 0,
            "stopped": 0,
            "skipped": 0
        }

,
        "totalJobs": 2,
        "completedJobs": 0,
        "billingMethod": "METERED",
        "seed": 2134223132,
        "appUpload": "arn:aws:devicefarm:us-west-2:123456789101:upload:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a993d0ffd4f8",
        "eventCount": 700,
        "jobTimeoutMinutes": 150,
        "devicePoolArn": "arn:aws:devicefarm:us-west-2:123456789101:devicepool:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/082d10e5-d7d7-48a5-ba5c-b33d66efa1f5",
        "radios": {
            "wifi": true,
            "bluetooth": false,
            "nfc": true,
            "gps": true
        }
    }
}

Listing 9-8Scheduling a test run with AWS CLI

项目 arn 被传递给--project-arn参数,上传 arn 被传递给--app-arn,设备池 arn 被传递给--device-pool-arn参数。

  • 清单 9-8 中安排的示例运行使用“Top Devices”设备池。

  • 从清单 9-8 中的命令输出中检索运行 ARN。这将用于从 AWS CLI 获取运行状态。

可以在 AWS CLI 上查看计划运行的状态,如清单 9-9 所示。

$ aws devicefarm get-run --arn arn:aws:devicefarm:us-west-2:123456789101:run:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/4f324434-2652-45f3-b065-9961e235cfd4 --region us-west-2
{
    "run": {
        "arn": "arn:aws:devicefarm:us-west-2:123456789101:run:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/4f324434-2652-45f3-b065-9961e235cfd4",
        "name": "SampleApp2.ipa",
        "type": "BUILTIN_FUZZ",
        "platform": "IOS_APP",
        "created": "2090-20-20T16:45:02.097000+00:00",
        "status": "RUNNING",
        "result": "PENDING",
        "started": "2090-20-20T16:45:02.097000+00:00",
        "counters": {
            "total": 0,
            "passed": 0,
            "failed": 0,
            "warned": 0,
            "errored": 0,
            "stopped": 0,
            "skipped": 0
        }

,
        "totalJobs": 2,
        "completedJobs": 0,
        "billingMethod": "METERED",
        "deviceMinutes": {
            "total": 0.0,
            "metered": 0.0,
            "unmetered": 0.0
        },
        "parsingResultUrl": "https://prod-us-west-2-results.s3-us-west-2.amazonaws.com/123456789101/abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/4f324434-2652-45f3-b065-9961e235cfd4/parsingResult.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20211017T164740Z&X-Amz-SignedHeaders=host&X-Amz-Expires=259200&X-Amz-Credential=AKIAUJHLTYS5AWNTRO6L%2F20211017%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=95e44a5eaf28a5ea66246a770b3fa85cc3b68e9b6f935e40720e809113094886",
        "seed": 2134223132,
        "appUpload": "arn:aws:devicefarm:us-west-2:123456789101:upload:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/0057dee1-a704-43f6-83dd-a993d0ffd4f8",
        "eventCount": 700,
        "jobTimeoutMinutes": 150,
        "devicePoolArn": "arn:aws:devicefarm:us-west-2:123456789101:devicepool:abcdefg2-46a7-4ebf-b3ab-7de683ad43cd/082d10e5-d7d7-48a5-ba5c-b33d66efa1f5",
        "radios": {
            "wifi": true,
            "bluetooth": false,
            "nfc": true,
            "gps": true
        }
    }

}

Listing 9-9Checking status of scheduled run

AWS CLI 上安排的运行也可以在 AWS 控制台上查看,如图 9-24 所示。

图 9-24

在 AWS 控制台上查看的 AWS CLI 上计划运行

测试运行完成后,可以在控制台上查看测试报告,如图 9-25 所示。

图 9-25

AWS CLI 上计划运行的测试报告

  • 该报告与图 9-13 所示相同,因为测试使用了相同的应用。

AWS 设备场 Jenkins 插件

AWS Device Farm 可以通过其插件与 Jenkins jobs 集成。通过这种集成,构建 iOS 应用的 Jenkins jobs 可以在构建后将工件发送到 AWS 设备场,以便在真实设备上进行测试,而无需手动干预。

安装插件

AWS Device Farm 插件可以通过 Jenkins 设置页面的管理插件选项与 Jenkins Web UI 一起安装,如图 9-26 所示。

图 9-26

访问 Jenkins 插件

可以搜索并安装插件,如图 9-27 所示。

图 9-27

正在安装 AWS 设备场 Jenkins 插件

配置插件

插件的配置包括提供 AWS 证书,插件将使用这些证书与您的 AWS 帐户中的 AWS 设备群进行交互。该插件支持 IAM 用户凭证或通过 IAM 角色获取临时凭证。无论使用哪种类型的 IAM 标识,插件都需要 AWS 设备场权限来提交测试运行。清单 9-10 显示了一个允许完整设备群访问的 IAM 策略示例。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DeviceFarmAll",
            "Effect": "Allow",
            "Action": [ "devicefarm:*" ],
            "Resource": [ "*" ]
        }
    ]
}

Listing 9-10Full AWS Device Farm access

通过将受管策略附加到插件将使用的 IAM 用户或 IAM 角色,也可以使用 AWS 设备场受管 IAM 策略。图 9-28 显示了附加到为设备群创建的 IAM 用户的 AWSDeviceFarmFullAccess 托管策略。

图 9-28

使用 AWS 设备场管理策略配置的 IAM 用户

同样,如果使用 IAM 角色来配置插件,图 9-29 显示了使用 AWSDeviceFarmFullAccess 托管策略的 IAM 角色。

图 9-29

使用 AWS 设备场管理策略配置的 IAM 角色

要配置插件,从 Jenkins 设置页面访问系统配置,如图 9-30 所示。

图 9-30

访问插件配置

在“配置”页面上,滚动到“AWS 设备场”部分。图 9-31 显示了带有 IAM 用户凭证的插件配置示例。

图 9-31

使用 IAM 用户凭据配置插件

要在插件中使用 IAM 角色,插件假设 Jenkins 全局环境配置了 AWS 凭证,并且这些凭证将用于承担该角色。

  • Jenkins 上的全局 AWS 凭证的形式可以是附加到 Jenkins 实例的 EC2 IAM 角色(如果 Jenkins 托管在 EC2 上)、在 Jenkins 实例上配置的 AWS 凭证环境变量等。

插件 IAM 角色必须配置为信任 Jenkins 环境使用的 IAM 实体(用户、角色)。清单 9-11 显示了插件 IAM 角色信任关系配置的一个例子。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "<IAM User or Role ARN for Jenkins Environment>"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Listing 9-11Trust relationship of the Plugin IAM role

Jenkins 环境中用于承担插件 IAM 角色的 IAM 凭据也必须拥有承担该角色的权限。清单 9-12 中显示了一个 IAM 策略示例,它显示了如何为 Jenkins 环境 IAM 用户或角色配置权限以承担插件 IAM 角色。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "<Role ARN of the Device Farm Plugin Role>"
    }
  ]
}

Listing 9-12Configuring permission to assume Plugin IAM role

在确保所有权限都配置为通过设备场插件使用 IAM 角色之后。图 9-32 显示了如何为插件配置 IAM 角色的示例。

图 9-32

使用 IAM 角色配置设备场插件

使用 Jenkins 自动化 AWS 设备群测试

在这一节中,我们将探讨如何将 AWS Device Farm 与 Jenkins 项目集成,该项目已在前一章中为自动化 iOS 应用构建进行了设置。将 AWS Device Farm 添加到 Jenkins 项目中,每当 Fastlane 开发一个应用时,都会自动开始设备场测试。

配置 Jenkins 项目

打开已被配置为构建 iOS 应用的现有 Jenkins 项目,并用清单 9-13 中所示的脚本替换构建脚本。

set +x

export TEAM_ID=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .TEAM_ID`

/usr/bin/xcodebuild build-for-testing -scheme SampleApp -destination generic/platform=iOS DEVELOPMENT_TEAM=$TEAM_ID s-allowProvisioningUpdates -derivedDataPath $WORKSPACE

mkdir Payload && cp -r $WORKSPACE/Build/Products/Debug-iphoneos/SampleApp.app Payload/

zip -r Payload.zip Payload && mv Payload.zip SampleApp.ipa

Listing 9-13Jenkins build script for Device Farm testing

该构建脚本从 AWS Secrets Manager 中检索 Apple team ID,并将其配置为环境变量,构建用于使用 Xcode 命令行工具(xcodebuild)进行测试的应用,将构建工件保存到 Jenkins workspace 目录中,并创建一个可测试的 ipa 文件,以备在 AWS 设备场中进行测试。

  • 使用前,在清单 9-13 提供的脚本中输入您的 Jenkins 工作空间目录。

在 Jenkins 上配置的构建脚本示例如图 9-33 所示。

图 9-33

Jenkins 上的设备场构建脚本

在构建脚本中创建的工件将被传递到 AWS 设备场进行测试,因此要配置 AWS 设备场,创建一个构建后操作,如图 9-34 所示。

图 9-34

Jenkins 后期构建操作

在后期构建操作中,选择在 AWS 设备群上运行测试,如图 9-35 所示。

图 9-35

运行 AWS 设备场测试的生成后操作

可提供如图 9-36 所示的配置。应该从下拉列表中选择用于测试的项目和设备池,应该在应用选项中提供构建后 ipa 在 Jenkins 工作区中的存储路径。

图 9-36

Jenkins 项目上的设备场构建后配置

图 9-36 中的示例显示了一个 ipa,它在构建后将被命名为 SampleApp.ipa,并存储在工作空间的根目录中(如清单 9-13 中所配置的)。

Jenkins 将在 AWS 设备场上创建的测试运行的名称也可以配置,默认情况下,build 标记用于命名创建的测试运行。

还应该选择要运行的测试框架和执行环境。图 9-37 显示了一个使用内置模糊测试框架并在定制环境中执行测试运行的例子。

图 9-37

配置测试框架和执行环境

触发 Jenkins 项目

通过在 AWS CodeCommit 中创建一个 commit,可以在 Jenkins 项目上触发自动构建。您还可以在 Jenkins 上手动启动一个构建来测试新处理的构建后操作。

可以如图 9-38 所示启动手动 Jenkins 构建。

图 9-38

开始手动 Jenkins 构建

清单 9-14 中显示了一个构建后设备群的 Jenkins 构建日志示例。正如所看到的,ipa 文件在测试安排之前首先被上传到 S3。运行也使用 Jenkins build 标记命名。

[AWSDeviceFarm] Using Project 'SampleApp'
[AWSDeviceFarm] Using DevicePool 'Top Devices'
[AWSDeviceFarm] Using App 'SampleApp.ipa'
[AWSDeviceFarm] Archiving artifact 'SampleApp.ipa'
[AWSDeviceFarm] Uploading SampleApp.ipa to S3
[AWSDeviceFarm] Waiting for upload SampleApp.ipa to be ready (current status: INITIALIZED)
[AWSDeviceFarm] Upload SampleApp.ipa succeeded
[AWSDeviceFarm] Getting test to schedule.
[AWSDeviceFarm] Scheduling 'BUILTIN_FUZZ' run 'jenkins-TestProject-96'
[AWSDeviceFarm] View the BUILTIN_FUZZ run in the AWS Device Farm Console: https://console.aws.amazon.com/devicefarm/home?#/projects/aaaabbbcc-33ab-4d34-87c6-576uhfdyur4/runs/abfj598n-ecfb-44cb-9d30-5958fhmfjhd
[AWSDeviceFarm] Waiting for test run to complete.

Listing 9-14Device Farm Jenkins build logs

一旦构建完成,可以在 Jenkins 项目主页上看到结果。该页面显示了处于通过、警告、跳过、失败、错误和停止状态的测试数量。图 9-39 显示,对于最近执行的测试,六项测试全部通过。

图 9-39

Jenkins 项目页面上的测试状态

可以在设备群控制台上查看详细的测试报告。图 9-40 显示了 Jenkins 测试运行的报告。

图 9-40

AWS 设备群控制台上的测试报告

摘要

将 AWS 设备场测试引入 iOS 应用开发,可以让您模拟真实环境来运行测试和重现问题,从而提高质量和用户体验。AWS Device Farm 可用的插件和 APS 也使得将它与开发工作流相集成变得可行。在本章中,我们探讨了 AWS device farm 的主要优势,并介绍了它如何与 Jenkins 上的 iOS 开发工作流集成。

在下一章中,我们将研究本章和前面章节中涉及的所有主要开发组件是如何作为持续集成持续交付(CICD)管道中的阶段被编排在一起的。

十、iOS 应用开发的持续交付渠道

持续集成持续交付(CICD)管道是从源代码和版本控制系统到向用户和客户交付新软件版本的软件开发步骤的自动化定义。在前面的章节中,我向 iOS 应用开发的不同方面和生命周期介绍了 DevOps 概念和工具,从构建、测试到交付。在这一章中,我将展示 CICD 管道如何帮助自动化和编排所有这些不同的组件到一个简化的过程中。

虽然 CICD 管道有多种选择,但我将重点关注 Jenkins 管道和 AWS 代码管道。我将展示这些管道类型如何与 iOS 开发工具集成,以实现 iOS 应用开发的 CICD。

Jenkins 管道公司

根据 Jenkins 网站的说法,“Jenkins Pipeline(或简称为大写“P”的“Pipeline”)是一套插件,支持将持续交付管道实现和集成到 Jenkins 中。”

对于使用 Jenkins Pipeline for CICD 的给定项目,管道被定义为名为“Jenkinsfile”的文本文件中的代码,并且该文本文件预计是项目源代码控制库的一部分,因此管道可以像应用代码的其余部分一样受到版本控制。编写管道 Jenkinsfile 时,支持的不同语法有声明式和脚本式。我将介绍声明性语法,因为它比较新,并且更容易阅读和理解 Jenkins 管道代码。另一方面,脚本语法遵循 Groovy 语言语法。

  • 作为在 Jenkinsfile 中定义语法的替代方法,管道语法也可以在 Jenkins UI 上定义,但最佳做法是将管道语法定义为代码,并将其与应用代码的其余部分一起存储,以便进行版本控制。

建立 Jenkins 管道的第一步是在 Jenkins 上创建管道。如图 10-1 所示,可以开始创建管道。

图 10-1

建立 Jenkins 管道

  • 避免在管道名称中使用空格,因为已知空格会在管道调用过程中导致问题。

就像前面章节中设置一个 Jenkins 项目一样,您可以使用 CodeCommit 存储库为 Jenkins 管道配置构建触发器,如图 10-2 所示。

图 10-2

为管道设置生成触发器

如图 10-3 所示,我正在配置管道以获取管道脚本,即来自源代码提交存储库的 Jenkinsfile,然后配置存储库和凭证。

图 10-3

配置管道定义位置

还必须定义管道脚本在存储库中的确切位置。在本例中,管道脚本位置的配置如图 10-4 所示。

图 10-4

配置管道脚本路径

配置好管道脚本路径后,保存管道创建即可完成创建,如图 10-4 所示。

  • Jenkins 管道脚本文件大多命名为 Jenkinsfile 该名称可以更改为您选择的任何名称。无论使用什么名称,都应如图 10-4 所示进行配置。

如图 10-4 所示,必须将 Jenkinsfile 添加到源存储库中。图 10-5 显示了添加 Jenkinsfile 后的存储库结构。

图 10-5

添加了 Jenkinsfile 的存储库结构

  • 图 10-5 所示的示例应用代码与前面章节中使用的代码相同。

Fastlane 测试阶段

已经在 Jenkins 上设置了 pipeline,并将 Jenkinsfile 添加到源存储库中,您可以通过向 Jenkinsfile 添加内容,开始向表示 iOS 应用开发过程中不同步骤的 Pipeline 添加阶段。首先让我们看看如何添加一个运行 Fastlane 测试的阶段。

清单 10-1 显示了一个 Jenkinsfile,它定义了运行 Fastlane 测试的单级管道。

pipeline {
    agent any
    stages {
        stage("Run fastlane test") {
            steps{
                sh """
                export LC_ALL=en_US.UTF-8 && export LANG=en_US.UTF-8
                fastlane test
                """
            }
        }
    }
}

Listing 10-1Single-stage Pipeline definition to run Fastlane test

当这些更改被提交并推送到 CodeCommit 时,管道触发并读取存储库中的 Jenkinsfile 来定义管道中的步骤。清单 10-1 中定义的流水线的成功执行如图 10-6 所示。

图 10-6

Fastlane 测试的单级流水线执行

  • Jenkins 一定能找到 Fastlane。如果出现找不到 Fastlane 的错误,请适当配置 Jenkins PATH 变量或在 Jenkinsfile 中指定 Fastlane 安装目录的完整路径。

此外,可以检索管道日志来查看执行和步骤的更多细节。图 10-6 中显示的管道执行的日志片段在清单 10-2 中给出。

Started by remote host SQSTrigger with note: User invoked: arn:aws:iam::123456789106:user/abdullahi2
Obtained jenkins/Jenkinsfile from git https://git-codecommit.us-east-1.amazonaws.com/v1/repos/devops-ios-repository
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
.
.
.
.
[Pipeline] // stage
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Run fastlane test)
[Pipeline] sh
+ export LC_ALL=en_US.UTF-8
+ LC_ALL=en_US.UTF-8
+ export LANG=en_US.UTF-8
+ LANG=en_US.UTF-8
+ fastlane test
.
.
.
.
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS

Listing 10-2Jenkins Pipeline execution logs

AWS 设备场测试阶段

要将设备场阶段添加到管道,必须安装 AWS 设备场 Jenkins 插件。在前一章中,我演示了如何使用 Jenkins freestyle 项目安装插件并与之交互。但是在这里,我们将通过管道与插件交互,所以让我们生成准确的语法来做到这一点。您可以从 Jenkins 管道中访问管道语法生成器,如图 10-7 所示。

图 10-7

访问管道语法生成器

如图 10-8 所示,从下拉选项中选择 AWS 设备农场步骤。

图 10-8

选择 AWS 设备场步骤

进入如图 9-36 和 9-37 所示的 Device Farm 测试配置(来自第九章),并为输入的配置生成如图 10-9 所示的流水线脚本。

图 10-9

为 AWS 设备场步骤生成管道脚本

应复制生成的管道脚本,并将其用于配置管道 Jenkinsfile 中的设备场阶段,如清单 10-3 所示,其中显示了将设备场阶段的配置附加到现有示例应用 Jenkinsfile。

pipeline {
    agent any
    environment {
        TEAM_ID = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .TEAM_ID'
        ).trim()}"""
    }
    stages {
        stage("Run fastlane test") {
            steps{
                sh """
                export LC_ALL=en_US.UTF-8 && export LANG=en_US.UTF-8
                fastlane test
                """
            }
        }
        stage("Run AWS Device Farm test") {
            steps {
                sh '/usr/bin/xcodebuild build-for-testing ​-scheme SampleApp -destination generic/platform=iOS DEVELOPMENT_TEAM=${TEAM_ID} ​-allowProvisioningUpdates -derivedDataPath ${WORKSPACE}'
                sh 'mkdir Payload && cp -r ${WORKSPACE}/Build/Products/Debug-iphoneos/SampleApp.app Payload/'
                'zip -r Payload.zip Payload && mv Payload.zip SampleApp.ipa'

                devicefarm appArtifact: 'SampleApp.ipa', appiumJavaJUnitTest: '', appiumJavaTestNGTest: '', appiumNodeTest: '', appiumPythonTest: '', appiumRubyTest: '', appiumVersionJunit: '1.4.16', appiumVersionPython: '1.4.16', appiumVersionTestng: '1.4.16', calabashFeatures: '', calabashProfile: '', calabashTags: '', deviceLatitude: 47.6204, deviceLocation: false, deviceLongitude: -122.3941, devicePoolName: 'Top Devices', environmentToRun: 'StandardEnvironment', eventCount: '', eventThrottle: '', extraData: false, extraDataArtifact: '', ifAppPerformanceMonitoring: true, ifBluetooth: true, ifGPS: true, ifNfc: true, ifSkipAppResigning: false, ifVideoRecording: true, ifVpce: false, ifWebApp: false, ifWifi: true, ignoreRunError: false, isRunUnmetered: false, jobTimeoutMinutes: 60, junitArtifact: '', junitFilter: '', password: '', projectName: 'SampleApp', radioDetails: false, runName: '${BUILD_TAG}', seed: '', storeResults: false, testSpecName: 'Default TestSpec for Android Appium Java Junit', testToRun: 'BUILTIN_FUZZ', uiautomationArtifact: '', uiautomatorArtifact: '', uiautomatorFilter: '', username: '', vpceServiceName: '', xctestArtifact: '', xctestFilter: '', xctestUiArtifact: '', xctestUiFilter: ''
            }
        }
    }
}

Listing 10-3Adding Device Farm Stage to Jenkins Pipeline

在现在添加的设备场阶段,定义了多个步骤。首先,应用是为使用 xcodebuild 进行测试而构建的,以生成测试工件。从生成的测试工件中,创建一个 ipa 文件并存储在一个位置,然后由设备群插件获取该文件以进行设备群测试运行。

环境变量也用于 TEAM_ID 的那个阶段。该环境变量在管道定义的环境部分中定义。环境变量的值是在运行时从 AWS Secrets Manager 中动态检索的。

当这些更改被提交并推送到 AWS CodeCommit 存储库时,管道就会触发。清单 10-3 中定义的流水线的成功执行如图 10-10 所示。

图 10-10

AWS 设备场测试的管道执行

测试结果也可以在 AWS 设备群上可视化,如图 10-11 所示。

图 10-11

Jenkins pipeline AWS 设备群测试结果

Fastlane 构建阶段

当所有的应用测试都通过后,通常下一步就是构建应用。这里,我们将添加一个阶段,在 Fastlane 和设备场测试成功后,构建应用以供 App Store 分发。

清单 10-4 显示了将 Fastlane 构建阶段附加到现有管道 Jenkinsfile 的代码片段。

pipeline {
    agent any
    environment {
        TEAM_ID = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .TEAM_ID'
        ).trim()}"""
        AWS_ACCESS_KEY_ID = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .AWS_ACCESS_KEY_ID'
        ).trim()}"""
        AWS_SECRET_ACCESS_KEY = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .AWS_SECRET_ACCESS_KEY'
        ).trim()}"""
        MATCH_PASSWORD = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .MATCH_PASSWORD'
        ).trim()}"""
        S3_BUCKET = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .S3_BUCKET'
        ).trim()}"""
        APP_IDENTIFIER = """${sh(
            returnStdout: true

,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .APP_IDENTIFIER'
        ).trim()}"""
        APPLE_DEVELOPER_USERNAME = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .APPLE_DEVELOPER_USERNAME'
        ).trim()}"""
    }

    stages {
        stage("Run fastlane test") {
            steps{
                       .
                       .
            }
        }
        stage("Run AWS Device Farm test") {
            steps {
                        .
                          .
            }
        }
        stage("Build app") {
            steps{
                sh """
                export LC_ALL=en_US.UTF-8 && export LANG=en_US.UTF-8
                fastlane build
                """
            }
        }
    }

}

Listing 10-4Adding Fastlane build stage to pipeline

在添加的 Fastlane 构建阶段,步骤包括设置一些特定于 Fastlane 的环境变量,并调用 Fastfile 中定义的构建通道。还定义了 Fastlane 所需的其他环境变量。所有这些环境变量值都是在运行时从 AWS Secrets Manager 中动态检索的。

将更改推送到 AWS CodeCommit 存储库后,清单 10-4 中定义的管道成功执行,如图 10-12 所示。

图 10-12

应用测试和构建的流水线执行

Fastlane 交付阶段

一个成功的 iOS 构建意味着应用已被签名,并准备好发布以进行试飞测试或提交到 App Store。在这里,我们将向管道添加一个阶段,调用应用中配置的 Fastlane Testflight lane,将应用交付给 App Store Connect,以便使用 Testflight 进行 beta 测试。

清单 10-5 显示了将交付阶段附加到现有管道 Jenkinsfile 以将构建的工件交付到 TestFlight 的代码片段。

pipeline {
    agent any
    environment {
        TEAM_ID = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .TEAM_ID'
        ).trim()}"""
        AWS_ACCESS_KEY_ID = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .AWS_ACCESS_KEY_ID'
        ).trim()}"""
        AWS_SECRET_ACCESS_KEY = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .AWS_SECRET_ACCESS_KEY'
        ).trim()}"""
        MATCH_PASSWORD = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .MATCH_PASSWORD'
        ).trim()}"""
        S3_BUCKET = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .S3_BUCKET'
        ).trim()}"""
        APP_IDENTIFIER = """${sh(
            returnStdout: true

,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .APP_IDENTIFIER'
        ).trim()}"""
        APPLE_DEVELOPER_USERNAME = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString ​--output text | jq -r .APPLE_DEVELOPER_USERNAME'
        ).trim()}"""
        APP_STORE_CONNECT_ISSUER_ID = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id app-store-connect-secret --query SecretString --output text | jq -r .APP_STORE_CONNECT_ISSUER_ID'
        ).trim()}"""
        KEY_ID = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id app-store-connect-secret --query SecretString --output text | jq -r .KEY_ID'
        ).trim()}"""
        API_KEY = """${sh(
            returnStdout: true,
            script: 'aws secretsmanager get-secret-value ​--secret-id app-store-connect-secret --query SecretString --output text | jq -r .API_KEY'
        ).trim()}"""
    }
    stages {
        stage("Run fastlane test") {
            steps{
                              .
                              .
            }

        }
        stage("Run AWS Device Farm test") {
            steps {
                              .
                              .
            }
        }
        stage("Build app") {
            steps{
                              .
                              .
            }
        }
        stage("Deliver app") {
            steps{
                sh """
                export LC_ALL=en_US.UTF-8 && export LANG=en_US.UTF-8
                fastlane testflight
                """
            }
        }
    }
}

Listing 10-5Adding Fastlane deliver stage to pipeline

在这里添加的交付阶段,步骤包括设置一些 Fastlane 特定的环境变量,并调用 Fastfile 中定义的 Testflight lane。还定义了 Fastlane 所需的附加环境变量,以便将构建工件上传到 App Store Connect。

清单 10-5 中定义的流水线成功执行如图 10-13 所示。

图 10-13

应用测试、构建和交付的管道执行

AWS 代码管道

AWS CodePipeline 是 AWS 的托管 CICD 服务。使用 CodePipeline,您可以自动化软件发布过程的不同阶段,而无需担心管理管道基础设施。它还在不同阶段与不同的 AWS 服务和第三方工具集成,以增强软件开发,例如,它与 Device Farm 集成以进行应用测试,与 GitHub 集成以进行源代码控制,与 Jenkins 集成以进行定制构建和测试阶段。

在接下来的部分中,我将介绍如何为 AWS 代码管道集成准备一个 Jenkins 环境,然后通过演示如何在 AWS 代码管道上使用 CICD 管道运行 Fastlane 测试和 AWS 设备场测试来深入研究集成。使用将要展示的概念,您将能够扩展您的 CICD 管道,以覆盖更多场景。

为 AWS 代码管道设置 Jenkins 环境

要在 AWS 代码管道上配置调用 Jenkins 进行自定义操作的管道,必须有一个外部 Jenkins 服务器,并且必须配置 Jenkins 服务器以启用与 AWS 代码管道服务的交互。

让我们探讨一些完成最终目标必须具备的先决条件。

设置 macOS 构建服务器

在本节中,我将使用 Jenkins 控制器和代理架构。请参考第四章,其中我介绍了如何提供 EC2 macOS 服务器并连接到它,并参考第五章,其中您看到了如何在 Linux 和 iOS 上设置 Jenkins 控制器,并使用 EC2 macOS 构建代理架构。

当设置成功时,在线 macOS 构建服务器将如图 10-14 所示。

图 10-14

EC2 macOS 在线构建服务器

验证 Fastlane 是否安装在 macOS 构建代理上,如清单 10-6 所示。

在 Jenkins 构建期间,AWS CLI 将用于检索存储在 AWS Secrets Manager 中的所有 Fastlane 机密,因此需要在 macOS 服务器上安装和配置 AWS CLI。

AWS CLI 可以按照清单 10-7 中所示进行验证和配置。

$ aws –-version
$ aws configure

Listing 10-7Verifying and configuring AWS CLI

jq 还用于在构建期间解析 jSON 数据,因此应该安装在 macOS 服务器上。可以用自制软件安装,如清单 10-8 所示。

$ brew install jq

Listing 10-8Verifying jq installation

设置 Xcode 和钥匙串访问

Xcode 必须使用将用于 Jenkins 作业的系统用户来安装和配置。

  • 通常,在构建代理上为 Jenkins 创建一个新用户,例如,在第五章设置 Jenkins 控制器和构建代理中,Jenkins 控制器将使用一个名为“Jenkins”的 Jenkins 用户通过 SSH 连接到 macOS 构建代理以提交构建作业。

  • 必须使用 Jenkins 用户,而不是默认的 ec2-user ,在 EC2 Mac 实例上安装和配置 Xcode。请参阅第四章,了解如何为 Jenkins 用户创建密码,并通过 VNC 上的 Jenkins 用户连接到您的 EC2 Mac 实例 UI。

此外,确保在构建服务器上的 Xcode 中正确配置了应用签名。图 10-15 显示了在 EC2 Mac 服务器上为将用于演示的示例应用配置 Xcode 签名和功能的示例。

图 10-15

Xcode 上的签名和功能设置

当使用 Mac server 作为构建代理在 Jenkins 上运行 CICD 进程时,构建通常会失败,因为在签名构建工件需要访问证书时,用户交互不可用于提供钥匙串密码。

为了防止这种情况,我将执行的步骤之一是在构建服务器钥匙串上配置签名证书,以便当 Xcode 在管道执行期间尝试使用它时,它允许访问而不提示输入密码。

图 10-16 所示的场景包括允许访问钥匙串中的证书。但是在使用“钥匙串”中的项目之前,钥匙串本身必须解锁。虽然这可以在管道执行期间自动完成,但需要钥匙串密码来解锁。在图 10-17 中,我将我的钥匙串密码存储在 AWS Secrets Manager 中,这样就可以在管道运行时检索到它。

图 10-17

将钥匙串密码存储在 AWS Secrets Manager 中

图 10-16

在钥匙串上配置签名证书权限

设置 EC2 IAM 角色

当将 Jenkins 与 AWS 代码管道集成时,Jenkins 服务器必须具有与 AWS 代码管道服务交互的权限,以轮询作业、报告作业状态等。对于所需的权限,有一个 AWS 管理的策略awscodepielinecustomactionaccess包含所有所需的权限。机密也存储在 AWS Secrets Manager 中,并在管道执行期间检索,因此必须向 Jenkins 服务器提供获取这些机密的权限。

当对 Jenkins 服务器使用 EC2 时,可以跨所有 Jenkins 节点(控制器和构建代理)使用单个 Jenkins EC2 IAM 角色来满足权限要求。图 10-18 显示了 Jenkins EC2 IAM 角色的权限配置示例。

图 10-18

Jenkins EC2 IAM 角色的权限配置

IAM 角色必须附加到所有 Jenkins 节点(控制器和 macOS 构建代理)。图 10-19 显示了一个将 EC2 IAM 角色附加到现有实例的例子。

图 10-19

将 IAM 角色附加到 Jenkins 实例

  • 应对所有使用中的 EC2 Jenkins 节点重复图 10-19 所示的示例流程。

可以从 Jenkins 实例中验证附加的 IAM 角色。清单 10-9 显示了如何验证正在使用的 AWS 身份的示例。响应中应返回附加的 IAM 角色名称。

$ aws sts get-caller-identity

{
    "UserId": "AROASOKDM2HTHY4MLKGHY:i-0846273b98d6d42f4",
    "Account": "123456789101",
    "Arn": "arn:aws:sts::123456789101:assumed-role/ec2-mac-role/i-0846273b98d6d42f4"
}

Listing 10-9Verifying AWS identity used on Jenkins instances

正在安装 AWS 代码管道 Jenkins 插件

要完成 Jenkins 环境设置,可以从 Jenkins 插件中心安装 AWS CodePipeline Jenkins 插件,如图 10-20 所示。

图 10-20

正在安装 AWS 代码管道 Jenkins 插件

在 AWS 控制台上设置代码管道

可以通过各种方式创建管道,如 AWS CLI、AWS SDKs、AWS 控制台等。我将使用 AWS 控制台来设置管道。从代码管道控制台开始创建管道,如图 10-21 所示。

图 10-21

从 AWS 控制台创建管道

对于管道设置,请提供一个名称并选择服务角色配置。在图 10-22 中,我选择为管道创建一个新的服务角色。

图 10-22

配置管道设置

接下来是配置管道的源阶段。在图 10-23 中,我配置了 CodeCommit 存储库,示例应用代码作为源代码存储在其中。

图 10-23

配置管道源阶段

在 AWS 控制台上创建管道时,source 之后的下一阶段默认为 Build ,并且不能修改。此外,一个管道必须包含至少两个阶段,所以在图 10-24 中,我配置了一个没有实际值的临时构建阶段来解决目前的限制。

图 10-24

配置临时构建阶段

有了源代码和构建阶段,我现在不需要任何进一步的阶段,所以我跳过部署阶段,如图 10-25 所示,继续创建管道。

图 10-25

跳过部署阶段创建

创建管道后,它会自动启动。由于构建阶段被配置为没有实际值的临时阶段,因此它将失败。您可以让管道失败,也可以停止管道执行。如图 10-26 所示,我停止了流水线执行。

图 10-26

创建后停止管道执行

既然已经建立了基本的管道,接下来,我将向您展示如何扩展这个管道,以便与 Jenkins 和 AWS Device Farm 集成,进行 iOS 应用测试。

使用 AWS CodePipeline 和 Jenkins 进行 Fastlane 测试

对于这种集成,您需要首先设置一个支持 CodePipeline 的 Jenkins 项目,然后在 CodePipeline 上配置一个自定义 stage 来与 Jenkins 项目集成。

配置 Jenkins 项目以测试应用

在这里,我将建立一个新的 Jenkins freestyle 项目,如图 10-27 所示,并将其配置为运行 Fastlane 测试。

图 10-27

为 Fastlane 测试创建 Jenkins 自由式项目

  • 记下项目名称,这将用于 AWS 代码管道的配置。

由于我正在为我的 Jenkins 环境使用控制器和构建代理架构,我将使用如图 10-28 所示的标签将此构建委托给我的 iOS 构建代理。

图 10-28

设置项目的运行位置

我们需要为源代码管理配置 AWS CodePipeline,因为该项目的源代码将由 AWS CodePipeline 传递。我的源代码管理设置如图 10-29 所示。

图 10-29

配置测试项目源代码管理

  • 应注意在 CodePipeline 操作类型配置中为 Provider 提供的值。这将在代码管道配置中使用。

构建触发器调用构建。为了确保在适当的时候调用构建,我将配置项目持续轮询 CodePipeline,以检查是否有任何与其配置匹配的挂起作业。如图 10-30 所示,我的项目将每分钟轮询一次 CodePipeline 中任何未完成的作业。

图 10-30

为项目配置生成触发器

Fastlane 测试的构建脚本如清单 10-10 所示。

set +x
echo "Set fastlane variables..."
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

echo "Starting Fastlane..."
fastlane test

Listing 10-10Fastlane testing build script

该脚本应进入项目的构建命令部分,如图 10-31 所示。

图 10-31

输入项目的构建脚本

项目配置的最后一步是添加一个 AWS code pipeline Publisher post build 动作,如图 10-32 所示。提供一个工件名称来标识从 Jenkins 项目发布的任何工件。

图 10-32

配置 AWS 代码管道发布者生成后操作

  • 记下配置的工件名称,因为它将在代码管道配置中使用。

向代码管道添加自定义阶段

要将创建的 Jenkins 项目添加到 AWS 代码管道,请编辑创建的管道,如图 10-26 所示。删除之前配置的临时搭建阶段,添加一个新的阶段,如图 10-33 所示。

图 10-33

删除现有的生成阶段并将新阶段添加到管道中

在新增加的阶段,增加一个新的 Jenkins 测试动作,如图 10-34 所示。

图 10-34

向新阶段添加新的 Jenkins 测试行动

  • 必须在测试类别下选择添加 Jenkins 操作,以匹配 Jenkins 项目中的配置。

配置 Jenkins 测试操作。在配置 Jenkins 项目时,可以从提供和记录的值中检索提供者名称、项目名称和输出工件字段。在服务器 URL 字段中,输入 Jenkins 控制器的公共 IP 地址。图 10-35 显示了我的 Jenkins 测试动作的配置。

图 10-35

配置 Jenkins 测试操作

一旦配置了操作,您现在将拥有一个两阶段管道。要开始管道执行,您可以将新提交推送到 CodeCommit 存储库,或者在 CodePipeline 控制台上手动发布更改。

图 10-36 显示了 Fastlane 测试的成功管道执行。

图 10-36

Fastlane 测试的成功管道执行

关于 Jenkins 项目执行的更多信息,可以从 Jenkins 获取构建日志。清单 10-11 显示了在 Jenkins 上为图 10-36 所示的管道运行生成的日志片段。

清单 10-11。Fastlane 测试代码管道执行的日志片段

AWS 设备群集成

将真实 iOS 设备上的测试添加到您的开发过程中是势在必行的,我将演示如何将 AWS 设备场测试的阶段添加到现有的 CICD 管道中。类似于之前配置的 Fastlane 阶段,我将首先设置一个支持代码管道的 Jenkins 项目来构建应用,之后我将设置一个用于测试的 AWS 设备场项目,然后最后在代码管道上配置一个设备场阶段,并使用与 Jenkins 和 AWS 设备场集成的单独操作。

配置 Jenkins 项目以构建测试应用

要在 Device Farm 上测试 iOS 应用,需要 ipa 包。这里创建的项目将用于生成可测试的 ipa 包,以供设备场使用。

这需要创建一个新的 Jenkins freestyle 项目,如图 10-27 所示。我还将确保这个项目在我的 iOS 构建代理上运行,如图 10-28 所示。对于源代码控制管理,虽然它与之前创建的项目相似,但我会更改一些字段以适应当前的用例,如图 10-37 所示。

图 10-37

配置生成项目源代码管理

在图 10-37 中,CodePipeline 动作类型类别被设置为 build,因为该项目被配置为 Build 动作,并且它将在 CodePipeline 上被配置为 Build 动作。

  • 记下提供者和 Jenkins 项目名称,因为这将在代码管道配置中使用。

这个项目的构建触发器将像之前为 Fastlane 测试创建的项目一样进行配置,如图 10-30 所示。

清单 10-12 中显示了将用于这个项目的构建脚本。

set +x

export TEAM_ID=`aws secretsmanager get-secret-value --secret-id fastlane-secrets --query SecretString --output text | jq -r .TEAM_ID`
export KEYCHAIN_PASSWORD=`aws secretsmanager get-secret-value ​--secret-id fastlane-secrets --query SecretString --output text | jq -r .KEYCHAIN_PASSWORD`

security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "$HOME/Library/Keychains/login.keychain"
/usr/bin/xcodebuild build-for-testing -scheme SampleApp ​-destination generic/platform=iOS DEVELOPMENT_TEAM=$TEAM_ID ​-allowProvisioningUpdates -derivedDataPath $WORKSPACE
mkdir Payload && cp -r $WORKSPACE/Build/Products/Debug-iphoneos/SampleApp.app Payload/
zip -r Payload.zip Payload && mv Payload.zip SampleApp.ipa

Listing 10-12App build for test script

如构建脚本所示,团队 ID 和钥匙串密码是从 AWS Secrets Manager 中检索的。在构建应用以使用 xcodebuild 进行测试之前,钥匙串密码用于解锁钥匙串。

脚本应该进入项目的构建命令部分,如图 10-38 所示。

图 10-38

输入项目的构建脚本

项目配置的最后一步是添加一个 AWS code pipeline Publisher post build 动作,如图 10-39 所示。提供一个工件名称来标识从这个 Jenkins 项目发布的任何工件。

图 10-39

配置 AWS 代码管道发布者生成后操作

  • 记下配置的工件名称,因为它将在代码管道配置中使用。

设置 AWS 设备场

我将使用在第九章中创建的设备农场项目。将使用的项目如图 10-40 所示。

图 10-40

AWS 设备场项目

要提交测试运行,您还需要有一个设备池。在本例中,我将使用托管的“顶级设备”设备池来测试我的应用。为了从 AWS CodePipeline 中使用这个设备池,我必须提供设备池 ARN,因此为了获得 ARN,使用可以从图 10-40 中检索的项目 ARN,我将使用清单 10-13 中所示的 AWS CLI。

  • 注意图 10-40 中显示的设备群项目 ID 和清单 10-13 中运行命令返回的设备池 ARN,因为这些将在管道配置中使用。
$ aws devicefarm list-device-pools --arn arn:aws:devicefarm:us-west-2:123456789101:project:3973dab9-33ab-4d34-87c6-3e183e009b07 --region us-west-2 --query 'devicePools[?name==`Top Devices`]'

Listing 10-13Getting device pool ARN

将设备场阶段添加到管道

我已经配置了一个 Jenkins 项目,它可以构建我的测试应用并生成工件,我还有一个设备场项目可供使用。现在,我将向管道中添加一个新的阶段。

编辑管道并添加新阶段,使其成为三阶段管道。图 10-41 显示了我给新舞台起的名字。

图 10-41

添加设备场阶段

添加新阶段后,您将配置第一个操作。这将是一个 Jenkins 构建操作,它将连接到之前创建的 Jenkins 项目。图 10-42 显示了如何添加一个 Jenkins 构建动作。

图 10-42

添加 Jenkins 构建操作

  • 必须在 Build 类别下选择 Add Jenkins 操作,以便与 Jenkins 项目中的配置相匹配。

提供者名称、项目名称和输出工件字段可以从配置 Jenkins 项目时提供和记录的值中检索。在服务器 URL 字段中,输入 Jenkins 控制器的公共 IP 地址。图 10-43 显示了我的 Jenkins 构建动作的配置。

图 10-43

配置 Jenkins 构建操作

接下来,在同一阶段,我们将配置设备场操作。设备场操作不能与 Jenkins 操作并行运行,因为设备场依赖于 Jenkins 操作生成的工件。可以添加一个新的动作组,如图 10-44 所示。

图 10-44

添加设备场操作

设备农场动作可以如图 10-45 所示进行配置。应该选择 AWS 设备场作为测试提供程序。Jenkins 操作中配置的输出工件必须配置为该操作中的输入工件,以便工件可以交换。此处应提供从设备场检索的项目 ID 和设备池 ARN。AppType、输入工件中 ipa 文件的路径和 TestType 也是必填字段。

图 10-45

配置设备场操作

  • AWS 设备场仅在美国西部-2 地区(俄勒冈州)可用,因此这必须是在 Pipeline 操作中选择的地区。

配置完这两个动作后,您应该有一个如图 10-46 所示的阶段。

图 10-46

配置了两个操作的设备场阶段

一旦配置了操作,您现在将拥有一个三级管道。要开始管道执行,您可以将新提交推送到 CodeCommit 存储库,或者在 CodePipeline 控制台上手动发布更改。

图 10-47 显示了 Fastlane 测试和 AWS 设备群测试的成功流水线执行。

图 10-47

Fastlane 测试和设备群测试的流水线执行

可以从 Jenkins 检索应用构建的构建日志,同时可以从设备群控制台查看设备群测试结果的详细信息。

摘要

CICD 管道使您能够协调应用开发的不同步骤和组件,从源代码控制到用户部署。在这一章中,我用真实的例子展示了不同风格的 CICD 管道,比如 Jenkins 管道和 AWS CodePipeline,是如何被用来编排我们在前面章节中涉及的不同概念的。

在 Jenkins Pipeline 中,我们看到了如何测试、构建应用并将其交付到 App Store Connect。在 AWS CodePipeline 中,我们涵盖了不同的测试选项,同时还集成了 Jenkins。AWS CodePipeline 可以进一步扩展,以添加额外的阶段,如 Jenkins Pipeline。例如,在设备场测试后,您可以添加一个额外的阶段,与 Jenkins 集成以构建一个应用,用于与 Fastlane 一起分发,甚至将应用交付到 App Store Connect。

posted @ 2024-08-12 11:20  绝不原创的飞龙  阅读(2)  评论(0编辑  收藏  举报