如何在 Ubuntu 16.04 上使用 Concourse CI 设置持续集成管道

介绍

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设置一个安全的反向代理。

在本教程中,大部分工作将在您的本地计算机上完成,而不是在 Concourse 服务器上完成。因此,您还需要确保在本地计算机上有几个工具。您需要一个文本编辑器(您可以在各种操作系统中找到一些例子是nano,vim,TextEdit,Sublime Text,AtomNotepad)来创建和修改存储库中的文件。您还需要在本地系统上安装和设置 Git,您可以通过遵循我们的 贡献开源:开始使用 Git指南来完成。

当您已设置 Concourse 服务器并在本地计算机上安装 Git 和文本编辑器时,请继续下方。

局部安装 Fly 指令线工具

当我们在先决条件下在服务器上安装 Concourse 时,我们在服务器上安装了命令行工具,以便我们可以从命令行管理 Concourse 实例。

要获取与您的服务器版本相匹配的本地副本fly,请访问您的 Web 浏览器中的 Concourse 实例:

1https://your_concourse_url

如果您已退出登录,或者您目前没有配置管道,则在窗口中间会显示下载飞行的链接:

Concourse fly big download link

如果您已登录并配置了管道,则飞行的下载链接将在屏幕的右下角可用:

Concourse fly small download link

点击代表本地计算机操作系统的图标下载二进制。

接下来,按照平台特定的指示在您的本地系统上设置飞行

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 按钮,在您的帐户中创建库存副本:

hello hapi fork repository

如果您是 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/tasksci/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

在本节中,我们定义了两个任务,每个任务由一个名称和一个计划组成。我们每个计划都包含gettask元素。

第一份工作没有任何任务陈述. 这有点不寻常,但当我们看看它在做什么以及如何使用时,它是有意义的。第一份得到陈述需要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 服务器并登录,您应该看到您的新管道被视觉定义:

Concourse inactive pipeline

正在等待的工作由灰色框表示,资源是较小的,黑暗的块. 由资源变化引发的工作是通过固体线连接的,而非引发的资源使用破线。

蓝色标题表示管道目前处于停机状态。 点击左上角的 菜单图标(三个堆积的水平线)以打开菜单。 您应该看到您的管道的条目(如果管道看不见,您可能需要退出并重新登录)。

Concourse unpause the pipeline

该管道现在应该不停,并将开始运作。

在一开始,各种资源和工作可能变成橙色,表明出现了错误,这是因为需要下载各种 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 running the test suite

黄色图表表明该工作目前正在进行中。 若要监控进展,请点击 ** 运行测试** 工作以查看当前的输出。

Concourse successful tests

点击图标返回主管道屏幕,每个职位的绿色状态表明最新委托已经通过了管道的所有阶段:

Concourse passed all jobs

管道将继续监控存储库,并随着变更而自动运行新的测试。

结论

在本指南中,我们设置了一个 Concourse 管道来自动监控存储库的更改。当发现更改时, Concourse 将下载存储库的最新版本,并使用 Docker 容器来安装和缓存项目依赖性。

Concourse 提供了大量的灵活性和能力来定义单独的测试程序,并将其存储在库内。

Published At
Categories with 技术
comments powered by Disqus