介绍
Concourse CI是一个现代化、可扩展的连续集成系统,旨在用可复制、可声明的语法自动化测试管道.在以前的指南中,我们 安装了Concourse在Ubuntu 16.04服务器上和 通过Let's Encrypt的SSL证书保护Web UI。
在本指南中,我们将展示如何使用Concourse自动运行项目的测试套件,当新的更改被承诺到存储库。
为了确保构建和测试程序始终与它们相关的代码保持同步,我们将将CI定义添加到应用程序存储库本身。之后,我们将使用Concourse的飞行
命令行工具将管道加载到Concourse中。
前提条件
在你开始之前,你需要一个 Ubuntu 16.04 服务器 **具有至少 1G 的 RAM **. 完成以下指南来设置一个非根用户,安装和配置 Concourse,安装 Nginx,获得 TLS/SSL 证书,并为 Concourse Web UI设置一个安全的反向代理。
- 初始服务器设置与Ubuntu 16.04
- 如何在Ubuntu 16.04上安装 Concourse CI
- 如何在Ubuntu 16.04上安装 Nginx
- 如何在Ubuntu 16.04上使用Let's Encrypt保护 Nginx
- 如何在Ubuntu 16.04上使用NGinx保护Concurse CI使用SSL
在本教程中,大部分工作将在您的本地计算机上完成,而不是在 Concourse 服务器上完成。因此,您还需要确保在本地计算机上有几个工具。您需要一个文本编辑器(您可以在各种操作系统中找到一些例子是nano
,vim
,TextEdit
,Sublime Text
,Atom
或Notepad
)来创建和修改存储库中的文件。您还需要在本地系统上安装和设置 Git,您可以通过遵循我们的 贡献开源:开始使用 Git指南来完成。
当您已设置 Concourse 服务器并在本地计算机上安装 Git 和文本编辑器时,请继续下方。
局部安装 Fly 指令线工具
当我们在先决条件下在服务器上安装 Concourse 时,我们在服务器上安装了飞
命令行工具,以便我们可以从命令行管理 Concourse 实例。
要获取与您的服务器版本相匹配的本地副本fly
,请访问您的 Web 浏览器中的 Concourse 实例:
1https://your_concourse_url
如果您已退出登录,或者您目前没有配置管道,则在窗口中间会显示下载飞行
的链接:
如果您已登录并配置了管道,则飞行
的下载链接将在屏幕的右下角可用:
点击代表本地计算机操作系统的图标下载飞
二进制。
接下来,按照平台特定的指示在您的本地系统上设置飞行
。
Linux 或 macOS
如果您的本地计算机运行 Linux 或 macOS,请在下载相应的二进制后遵循这些说明。
首先,将下载的二进制标记为可执行,我们将假设您已将文件下载到您的~/Downloads
目录,因此在需要时调整下载位置:
1[environment local]
2chmod +x ~/Downloads/fly
接下来,将二进制安装到您的路径中的一个位置,键入:
1[environment local]
2sudo install ~/Downloads/fly /usr/local/bin
您可以通过键入验证可执行的可用性:
1[environment local]
2fly --version
1[secondary_label Output]
2[environment local]
33.3.1
如果您可以查看版本,则fly
已成功安装。
窗口
如果您的本地计算机运行 Windows,请按键盘上的 Windows 键,键入 powershell,然后按 ENTER。
在出现的窗口中,通过键入创建一个bin
文件夹:
1[environment local]
2mkdir bin
接下来,将fly.exe
文件从您的下载
文件夹移动到新的bin
文件夹,键入:
1[environment local]
2mv Downloads/fly.exe bin
查看您是否已有 PowerShell 配置文件:
1[environment local]
2Test-Path $profile
如果答案是真
,那么你已经有个人资料了。
如果答案是错误
,您需要通过键入创建一个:
1[environment local]
2New-Item -path $profile -type file -force
1[secondary_label Output]
2[environment local]
3
4 Directory: C:\User\Sammy\Documents\WindowsPowerShell
5
6Mode LastWriteTime Length Name
7---- ------------- ------ ----
8-a---- 7/9/2017 5:46 PM 0 Microsoft.PowerShell_profile.ps1
一旦你有一个个人资料,用你的编辑器编辑它:
1[environment local]
2notepad.exe $profile
在编辑器窗口中(如果您需要创建您的个人资料,它将是空的),添加以下行:
1[label Microsoft.PowerShell_profile.ps1]
2[environment local]
3$env:path += ";C:\Users\Sammy\bin"
保存并关闭文件,当你完成。
接下来,为当前用户设置执行策略为RemoteSigned
,以允许PowerShell读取配置文件:
1[environment local]
2Set-ExecutionPolicy -scope CurrentUser RemoteSigned
最后,通过键入源PowerShell配置文件:
1[environment local]
2. $profile
您现在应该能够从任何位置调用fly.exe
可执行。
1[environment local]
2fly.exe --version
1[secondary_label Output]
2[environment local]
33.3.1
在本指南中,您需要将fly
命令的每个实例替换为fly.exe
,以匹配Windows命令。
通过 Concourse 服务器进行身份验证
安装飞
后,登录您的远程 Concourse 服务器,以便您可以本地管理您的 CI 环境. 一个单一的飞
二进制可用于联系和管理多个 Concourse 服务器,因此命令使用一个名为目标
的概念作为标签来识别您要发送命令的服务器。
在本指南中,我们正在使用 main作为我们 Concourse 服务器的目标名称,但您可以替代您想要的目标名称。输入您的 Concourse 服务器的域名,在 -c
选项之后,输入 https://
协议规格,以表示您的服务器位置:
1[environment local]
2fly -t main login -c https://example.com
您将被要求在 Concourse 服务器上的 /etc/concourse/web_environment
文件中输入您配置的用户名和密码:
1[secondary_label Output]
2[environment local]
3logging in to team 'main'
4
5username: sammy
6password:
7
8target saved
一旦您验证,飞
工具将创建一个名为~/.flyrc
的配置文件,以便为未来的命令存储您的身份证。
<$>[注]
注: 如果您稍后升级了Concourse版本,您可以通过键入以下方式安装飞
命令的匹配版本:
1fly -t main sync
这将更新您的系统上的飞行
二进制,同时保持您的配置完整。
铸造和克隆示例存储库
现在你已经在你的系统上设置了飞行
,我们可以继续设置我们将使用的存储库来展示Concourse管道。
在您的网页浏览器中,请访问GitHub上的hello hapi
应用程序(https://github.com/do-community/hello_hapi),我们将作为我们的示例。这个应用程序是一个简单的hello world
程序,有几个单元和集成测试,用Hapi.js(https://hapijs.com/)编写,一个Node.js网络框架。
由于此示例用于展示各种连续集成系统,您可能会注意到一些用于为其他系统定义管道的文件。
要创建您的库存,请登录 GitHub 并导航到 项目库. 点击右上角的 Fork 按钮,在您的帐户中创建库存副本:
如果您是 GitHub 组织的会员,您可能会被问到您想在哪里分叉存储库.一旦您选择一个帐户或组织,存储库的副本将添加到您的帐户中。
接下来,在本地计算机上的终端中,移动到您的主目录:
1[environment local]
2cd $HOME
使用以下命令将存储库克隆到本地计算机,取代您自己的 GitHub 用户名:
1[environment local]
2git clone [email protected]:your_github_user/hello_hapi
在您的主目录中将创建一个名为hello_hapi
的新目录。
1[environment local]
2cd hello_hapi
我们将为该存储库内的示例项目定义一个连续的集成管道. 在做出任何更改之前,最好在 Git 中创建并切换到一个新的分支,以便分离我们的更改:
1[environment local]
2git checkout -b pipeline
1[secondary_label Output]
2[environment local]
3Switched to a new branch 'pipeline'
现在我们有一个新的分支机构,我们可以开始定义我们的持续一体化管道。
设置应用程序的连续集成过程
我们将在项目存储库内部定义我们的管道和所有相关文件,这有助于确保持续的集成流程始终与其测试的代码保持同步。
测试套件已经被定义在一个名为测试
的目录中。它包括一个单元测试和两个基本集成测试。在脚本
对象中的package.json
文件中定义了运行测试的命令。在安装了npm
和Node.js的环境中,您可以通过键入npm test
来运行测试(在安装了npm install
的项目依赖性之后)。
要开始,在存储库中创建一个名为ci
的目录,以容纳项目的连续集成资产,我们还将创建两个名为ci/tasks
和ci/scripts
的子目录,以保留管道引用和任务呼叫的脚本的个别任务定义。
通过键入创建所需的目录结构:
1[environment local]
2mkdir -p ci/{tasks,scripts}
接下来,我们可以开始创建 Concourse 将使用的个别文件。
定义管道
用文本编辑器创建并在ci
目录中打开名为pipeline.yml
的文件(我们将在本指南中显示nano
编辑器,但您应该替代您的系统的文本编辑器)。
1[environment local]
2nano ci/pipeline.yml
我们现在可以开始建立我们的管道。
定义 NPM 缓存资源类型
在文件内部,我们将通过定义一个新的资源类型开始:
1[label ci/pipeline.yml]
2[environment local]
3---
4resource_types:
5 - name: npm-cache
6 type: docker-image
7 source:
8 repository: ymedlop/npm-cache-resource
9 tag: latest
为了将连续集成过程与通过系统传输的数据分离开来,Concourse将所有状态信息卸载到称为 resources的抽象中。资源是外部数据源,Concourse可以用来从信息中提取或推送信息。
resource_types标题允许您定义您可以在管道中使用的新类型的资源,例如电子邮件通知、Twitter集成或RSS源。我们定义的新资源类型告诉 Concourse 如何使用 npm-cache-resource,该资源作为 Docker 图像提供,允许 Concourse 安装 Node.js 项目的依赖性,并在任务之间共享。
定义库和缓存资源
接下来,我们需要定义管道的实际资源:
1[label ci/pipeline.yml]
2[environment local]
3. . .
4
5resources:
6 - name: hello_hapi
7 type: git
8 source: &repo-source
9 uri: https://github.com/your_github_user/hello_hapi
10 branch: master
11 - name: dependency-cache
12 type: npm-cache
13 source:
14 <<: *repo-source
15 paths:
16 - package.json
本节定义了 Concourse CI 的工作需要完成任务的两个资源。 Concourse 使用资源定义来监控上游系统的变化,并了解如何在工作需要时将资源拖下来。
第一個資源代表你在GitHub上的「hello_hapi」儲存庫的叉子。「來源」行包含一個名為「repo-source」的YAML(http://www.yaml.org/spec/1.2/spec.html#id2785586),標籤元素以供未來參考。
第二个资源,称为dependence-cache
,使用我们定义的npm-cache
资源类型来下载项目的依赖性。在该资源的源
规格中,我们使用<<: *repo-source
行到_reference_
和_extend_
指向&repo-source
的元素。
定义依赖性收集和测试工作
最后,我们定义了使用Concourse jobs的实际持续整合过程:
1[label ci/pipeline.yml]
2[environment local]
3. . .
4
5jobs:
6 - name: Install dependencies
7 plan:
8 - get: hello_hapi
9 trigger: true
10 - get: dependency-cache
11 - name: Run tests
12 plan:
13 - get: hello_hapi
14 trigger: true
15 passed: [Install dependencies]
16 - get: dependency-cache
17 passed: [Install dependencies]
18 - task: run the test suite
19 file: hello_hapi/ci/tasks/run_tests.yml
在本节中,我们定义了两个任务,每个任务由一个名称和一个计划组成。我们每个计划都包含get
和task
元素。
第一份工作没有任何任务陈述. 这有点不寻常,但当我们看看它在做什么以及如何使用时,它是有意义的。第一份得到陈述需要hello_hapi
资源并指定触发器:真的
选项。
第一个工作中的第二个得到声明(‘get: dependency-cache’)需要我们定义的资源来下载和缓存该项目的 Node.js 依赖性。这个声明评估了在 package.json
文件中发现的要求并下载它们。
<$>[注意] 注意:在这个具体的例子中,只有一个额外的工作,所以将 Node.js 依赖作为一个独立步骤的缓存的好处并未完全实现(将接收声明添加到下面的测试任务就足以下载依赖)。
第二个工作(‘名称:运行测试’)始于声明相同的依赖性与一个显着的差异。过渡
的限制导致获得声明只匹配已成功穿过管道中的以前步骤的资源。
获取陈述后,一个名为运行测试套件
的任务被定义,而不是定义完成内线的步骤,它告诉Concourse从收集的存储库中提取定义。
当你完成时,整个管道应该是这样的:
1[label ci/pipeline.yml]
2[environment local]
3---
4resource_types:
5 - name: npm-cache
6 type: docker-image
7 source:
8 repository: ymedlop/npm-cache-resource
9 tag: latest
10
11resources:
12 - name: hello_hapi
13 type: git
14 source: &repo-source
15 uri: https://github.com/your_github_user/hello_hapi
16 branch: master
17 - name: dependency-cache
18 type: npm-cache
19 source:
20 <<: *repo-source
21 paths:
22 - package.json
23
24jobs:
25 - name: Install dependencies
26 plan:
27 - get: hello_hapi
28 trigger: true
29 - get: dependency-cache
30 - name: Run tests
31 plan:
32 - get: hello_hapi
33 trigger: true
34 passed: [Install dependencies]
35 - get: dependency-cache
36 passed: [Install dependencies]
37 - task: run the test suite
38 file: hello_hapi/ci/tasks/run_tests.yml
保存并关闭文件,当你完成。
定义测试任务
虽然管道定义概述了我们连续集成过程的结构,但它推迟了将实际的测试任务定义到另一个文件中。
在ci/tasks
目录中打开一个名为run_tests.yml
的新文件:
1[environment local]
2nano ci/tasks/run_tests.yml
要定义一个任务,您需要指定工人需要的操作系统类型,定义执行任务所用的图像,命名任务将使用的任何输入或输出,并指定要运行的命令。
插入以下内容来设置我们的测试任务:
1[label ci/tasks/run_tests.yml]
2[environment local]
3---
4platform: linux
5
6image_resource:
7 type: docker-image
8 source:
9 repository: node
10 tag: latest
11
12inputs:
13 - name: hello_hapi
14 - name: dependency-cache
15
16run:
17 path: hello_hapi/ci/scripts/run_tests.sh
在上面的配置中,我们指定了这个任务需要一个Linux工人,而Concourse服务器本身可以满足这个要求,而无需额外配置。
接下来,我们表示一个图像,将由工人使用来执行任务. 虽然你可以创建和使用自己的图像类型,在实践中,这将几乎总是是一个Docker图像. 由于我们的库是一个Node.js应用程序,我们选择了最新的节点
图像来运行我们的测试,因为它已经安装了相应的工具。
Concourse 任务可以指定输入和输出,以表明它需要访问的资源和它将产生的文物。输入与以前在工作
级别中拉下来的资源相匹配。这些资源的内容被提供给任务环境的顶级目录,可以在任务运行期间进行操纵。在这里,应用程序存储库将在hello_hapi
目录下提供,Node.js 依赖性将在名为cache-dependence
目录下提供。
最后, run 项列出了要执行的命令的 path。每个任务只能是具有参数的单一命令,所以虽然可以通过编写 bash 字符串来构建命令内线,但更常见的是将任务指向脚本文件。
保存并关闭文件,当你完成。
定义测试脚本
最后,我们需要创建该任务将执行的脚本. 打开一个名为 run_tests.sh
的新文件,位于 ci/scripts/run_tests.sh
:
1[environment local]
2nano ci/scripts/run_tests.sh
此脚本将操纵测试环境的输入以将项目移动到正确的位置,然后通过运行npm 测试
来运行存储中定义的测试套件。
将以下内容添加到新文件中:
1[label ci/scripts/run_tests.sh]
2[environment local]
3#!/usr/bin/env bash
4
5set -e -u -x
6
7mv dependency-cache/node_modules hello_hapi
8cd hello_hapi && npm test
首先,我们表示该脚本应该由Docker容器的bash
解释器执行。设置
选项修改壳的默认行为,以引起任何错误或不设置变量,以阻止脚本执行,并在执行时打印每个命令。
我们运行的第一个命令将位于node_modules
目录中的缓存依赖从dependency-cache
目录中移动到hello_hapi
目录中。记住,这两个目录都可用,因为我们在任务定义中指定了它们作为输入。
之后,我们进入应用程序存储库并运行npm 测试
,执行定义的测试套件。
完成后,保存并关闭文件。
在继续之前,将新脚本标记为可执行,以便直接运行:
1[environment local]
2chmod +x ci/scripts/run_tests.sh
我们的管道和所有相关文件已定义。
在竞赛中设置管道
在我们将管道
分支再合并到主
并将其推向GitHub之前,我们应该继续将我们的管道加载到Concourse中。
虽然我们需要手动加载管道,因为Concourse执行管道,它会从存储库中的目录中读取任务和脚本. 对管道本身的任何更改都需要重新加载到Concourse才能生效,但由于我们没有定义所有内容,当任务或脚本的更改被自动注意到时,它们将被上传为委托的一部分。
要设置一个新的管道,用 Fly 命令瞄准您的 Concourse 服务器,使用设置管道
操作. 我们需要通过新的管道的名称与-p
选项,并通过管道配置文件与-c
选项:
1[environment local]
2fly -t main set-pipeline -p hello_hapi -c ci/pipeline.yml
您将被要求在继续之前确认配置。键入 y并点击 ENTER:
1[secondary_label Output]
2[environment local]
3. . .
4
5apply configuration? [yN]: y
6pipeline created!
7you can view your pipeline here: https://example.com/teams/main/pipelines/hello_hapi
8
9the pipeline is currently paused. to unpause, either:
10 - run the unpause-pipeline command
11 - click play next to the pipeline in the web ui
正如输出所示,管道已被接受,但目前暂停。您可以使用飞
或Web UI暂停管道,我们将使用Web UI。
在您的 Web 浏览器中,访问您的 Concourse 服务器并登录,您应该看到您的新管道被视觉定义:
正在等待的工作由灰色框表示,资源是较小的,黑暗的块. 由资源变化引发的工作是通过固体线连接的,而非引发的资源使用破线。
蓝色标题表示管道目前处于停机状态。 点击左上角的 菜单图标(三个堆积的水平线)以打开菜单。 您应该看到您的管道的条目(如果管道看不见,您可能需要退出并重新登录)。
该管道现在应该不停,并将开始运作。
在一开始,各种资源和工作可能变成橙色,表明出现了错误,这是因为需要下载各种 Docker 图像,而管道
分支仍然需要合并到我们的存储库的主要
分支,以使任务和脚本文件可用。
承诺改变去
现在,随着连续集成过程的定义,我们可以将其委托到我们的git
存储库,并将其添加到Concourse中。
将新的ci
目录添加到阶段区域,键入:
1[environment local]
2git add ci
通过检查状态来验证要执行的文件:
1[environment local]
2git status
1[secondary_label Output]
2[environment local]
3On branch pipeline
4Changes to be committed:
5 (use "git reset HEAD <file>..." to unstage)
6
7 new file: ci/pipeline.yml
8 new file: ci/scripts/run_tests.sh
9 new file: ci/tasks/run_tests.yml
通过键入进行更改:
1[environment local]
2git commit -m 'Add Concourse pipeline'
这些变化现在已经对我们的管道
分支进行了承诺,我们可以通过切换分支和合并将分支重新合并为主
分支:
1[environment local]
2git checkout master
3git merge pipeline
现在,将新更改的主
分支推回到GitHub:
1[environment local]
2git push origin master
承诺将在60秒内启动新构建,并在删除更改后,Concourse将能够访问管道任务和脚本。
观看新建筑
在Concourse Web UI中,一个新的构建将在下一分钟内开始通过管道进行进展:
黄色图表表明该工作目前正在进行中。 若要监控进展,请点击 ** 运行测试** 工作以查看当前的输出。
点击家
图标返回主管道屏幕,每个职位的绿色状态表明最新委托已经通过了管道的所有阶段:
管道将继续监控存储库,并随着变更而自动运行新的测试。
结论
在本指南中,我们设置了一个 Concourse 管道来自动监控存储库的更改。当发现更改时, Concourse 将下载存储库的最新版本,并使用 Docker 容器来安装和缓存项目依赖性。
Concourse 提供了大量的灵活性和能力来定义单独的测试程序,并将其存储在库内。