介绍
软件工程是一个快速发展且竞争激烈的领域。更快地向用户推出产品将使您在竞争对手中占据优势。好的一面是,行业最佳实践已经到位,可以帮助企业拥有一个公平的竞争环境。
持续集成和持续开发(CICD)是利用行业最佳实践在这一竞争领域中为企业提供优势的策略示例。
GitHub 是一个基于 Web 的托管仓库,结合了版本控制工具 Git,允许软件开发人员、工程师和架构师实现 CI/CD。持续开发(CD)是自动构建、测试和部署的实践。持续集成(CI)使许多人能够协作处理同一个项目,并检查代码是否正常运行,而无需担心合并冲突。
GitHub Actions 允许我们编写自动构建、测试和部署的步骤。
在本教程中,您将学习如何使用 GitHub Actions 设置持续集成。我们将首先设置一个 Git 仓库来托管我们的代码。然后,我们将配置一个 GitHub CI 流程来监视代码中的更改,启动 CI 运行器(runner)来运行测试、构建我们的应用程序并将其部署到运行 Nginx 的 Ubuntu 22.04 服务器上。
前提条件
要学习本教程,您需要满足以下条件:
-
一台运行 Ubuntu 22.04 的服务器。您可以按照本教程进行初始 Ubuntu 服务器设置, 添加非 root 用户,以及启用 Ubuntu 的 UFW 防火墙.
-
您需要在服务器上安装 Node.js,最好是 14 及以上版本。我们有一篇关于如何在 Ubuntu 上安装 Node.js.
-
您需要安装 Nginx 服务器软件。我们有一篇关于如何在运行 Ubuntu 的服务器上安装 Nginx.
-
您将需要 Docker 和Docker Compose安装在您的本地机器上,以运行隔离的开发环境。请按照我们的教程学习如何在云端安装和操作 Docker。
现在我们已经准备好了所需的一切,让我们开始吧。
步骤 1. 克隆项目仓库。
我们将本教程基于Reactjs,一个用于构建用户界面的声明式 Javascript 库。如果您想从头开始设置一个新项目,可以使用这个关于设置 React 应用的资源。为了简便起见,我们将使用这个已在 GitHub 上设置好的React.js 仓库的克隆版本。
我们克隆的应用程序是一个简单的 React 应用程序,带有react-router 6以及使用React Testing Library进行的测试,它为我们提供了访问 DOM 的方法。
要克隆仓库,请点击绿色按钮并复制 URL。

在您的工作区中打开终端,并运行以下命令来克隆应用程序:
|
1 |
git clone git@github.com:EspiraMarvin/cicd-tut.git |
克隆仓库后,进入项目目录:
|
1 |
cd cicd-tut |
运行 docker-compose up 命令来构建并运行应用程序:
|
1 |
docker-compose up --build --force-recreate |
当过程完成后,访问 http://localhost:3000
您应该会看到类似于以下内容:

步骤 2. 理解 Node.js.yml 文件。
在这一步中,我们将定义 GitHub Yaml 文件中的指令,以帮助我们理解发生了什么。在仓库中,有一个目录 .github/workflows,其中包含一个 node.js.yml 文件,该文件包含在您将更改推送到 GitHub 上的代码仓库后,GitHub 运行器(runners)所遵循的工作流步骤。 YAML 语法用于编写 GitHub Actions 的工作流。YAML 文件以扩展名 yaml 或 yml.
打开 node.js.yml 文件,它应该看起来像这样:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
name: cicd-tut on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: # 运行该作业的运行器类型 runs-on: self-hosted strategy: matrix: node-version: [16.x] # 步骤代表将作为作业一部分执行的任务序列 steps: - name: 'checkout' uses: actions/checkout@v3 - name: 'setup node actions' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build # - run: cp -r ~/actions-runner/cicd-react/react-tut-test/react-tut-test/build /var/www/react-cicd |
在编写本教程时,我们使用的是 Node.js 16 的版本 16。现在,让我们来了解一下 GitHub Actions 工作流:
-
name
name: cicd-tut
工作流的名称,该名称将显示在您的仓库 Actions 标签页。
-
on
|
1 2 3 4 5 |
on: push: branches: [ "main" ] pull_request: branches: [ "main" ] |
on 用于定义事件。事件可以自动触发工作流,也可以计划在以后运行。事件可以是单个或多个,您还可以将工作流执行指定给特定的分支、标签或文件。这就像一个过滤器。
在我们的 YAML 文件中,我们定义了多个自动事件,它们是:
-
一个 push 事件会在代码提交到仓库时被触发
-
一个 pull_request 事件会在主分支上创建拉取请求(pull request)时被触发。
我们指定了一个分支名称 main ,以便将工作流的执行限制为仅该分支。我们还可以使用 ! 标志后跟分支名称来指定要忽略的分支。
-
jobs
工作流本质上由一个或多个作业(job)组成。这些作业从第一个到最后一个依次运行。
|
1 2 3 4 |
jobs: build: # 运行该作业的运行器类型 runs-on: self-hosted |
每个作业都在由 runs-on 指定的运行器环境中运行。您可以选择在由 ubuntu-latest 表示的 GitHub 运行器上运行作业,或者在由 self-hosted 运行器表示的 self-hosted 运行器上运行。您的选择将取决于您需要的作业数量。使用自托管(self-hosted)运行器,您可以获得更多的灵活性和对资源的控制。
在下一步中,我们将首先在 GitHub 运行器上运行作业,稍后,我们将在自己的服务器上设置 GitHub 自托管运行器。
-
strategy
策略(Strategy)允许我们在单个作业定义中使用变量,以根据变量的组合自动创建多个作业运行。
在我们的 YAML 文件中,我们有一个用于 node-version 的变量,但如果我们像这样添加另一个用于 node 版本 18 的变量: node-version: [16.x, 18.x],那么矩阵(matrix)策略将为我们的 React 应用程序针对 16 和 18 两个 Node 版本创建 2 个作业运行。
|
1 2 3 |
strategy: matrix: node-version: [16.x] |
-
steps
步骤(Steps)是构成作业的任务序列。步骤可以运行命令、设置任务、运行公共仓库中的 action,或运行在 Docker 注册表中发布的 action。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
steps: - name: 'checkout' uses: actions/checkout@v3 - name: 'setup node actions' uses: actions/setup-node@v3 with: node-version: "16" cache: 'npm' - run: npm i - run: npm test - run: npm run build |
步骤有一个名称。虽然它是可选的,但您可以使用它来指定一个简单的方法来标识将在 GitHub 上显示的步骤名称。
在步骤中,您可以选择要在作业中运行的操作(action),操作是可重用的。在定义操作时会指定操作的版本,这非常重要,因为它可以防止在操作所有者发布更新时破坏您的工作流。
在上述代码片段中, checkout@v3 是一个指定了版本的操作示例 3。此操作会检出您的仓库,以便您的工作流可以访问它。
某些操作(例如 actions/setup-node@v3 上方)具有使用 with 关键字表示的输入,setup node 操作需要缓存 Node 版本 16 和 npm。
-
run
此操作使用操作系统的 shell 运行命令行程序。
在上述 YAML 文件中,我们有三个命令,它们都将在运行器(runner)环境中使用相同的 shell 运行。
-
第一个命令 npm i 安装我们 React 应用所需的所有依赖项。
-
第二个 npm test,运行我们编写的测试。该测试期望文本 learn react 渲染在主页上。
-
最后, npm run build 命令会创建一个包含我们应用生产版本构建的 build 目录。稍后,我们将在我们的 Nginx 服务器块.
步骤 3。使用 GitHub 运行器测试 GitHub CI。
在此步骤中,我们将使用 GitHub 运行器测试持续集成流程。首先打开 node.js.yml 文件。将操作运行的运行器类型修改为 ubuntu-latest。这样做的目的是在设置我们自己的自托管运行器之前,测试 GitHub 工作流是否在 GitHub 运行器上完美运行。
|
1 2 3 |
jobs: build: runs-on: ubuntu-latest |
在您的 GitHub 账户 上创建一个新仓库。在继续之前,返回您的工作区目录并删除 .git 目录,如果您看不到它,请检查您的隐藏文件。您可以在终端上使用以下命令来删除该目录:
|
1 |
rm -rf .git |
现在您可以 git add 所有项目文件,提交并推送它们到您的仓库。如果遇到困难,请使用此指南来 将您的项目文件夹连接到您在上面创建的 GitHub 仓库。
完成后,点击您仓库中的 Code 选项卡,您会在总提交次数旁看到一个橙色小点,点击它时,您会看到一个类似于下图的模态框,表示您的工作流已进入队列:

现在点击模态框上的 Details 链接,或者转到 Actions 选项卡,您将看到 GitHub 运行器正在运行 node.js.yml 工作流的每个步骤:

如果成功,点击 Actions 选项卡,它应该看起来像这样:

就是这样,我们 Code 选项卡上的橙色小点现在应该变成了一个绿色对勾。GitHub 运行器已成功构建了我们的应用。
现在,让我们更进一步,将构建环境更改为在我们自己的 Ubuntu 服务器基础设施.
步骤 4。设置 GitHub 工作流以使用自托管运行器。
在我们在服务器中安装自托管运行器之前,让我们回到工作区,并编辑 node.js.yml 工作流文件,使其在 GitHub 自托管运行器上运行。
|
1 2 3 |
jobs: build: runs-on: self-hosted |
在此阶段,当您提交更改时,由于尚未定义自托管运行器,该作业将排队等待。
在您的仓库中,点击
Settings 选项卡,在左侧边栏中点击
Actions,然后点击
Runners:

点击 New self-hosted runner,然后选择 Linux 作为操作系统。
您将看到说明,向您展示如何下载运行器并将其安装在您的服务器上。
步骤 5。在我们的服务器上安装和配置 GitHub 自托管运行器。
在此步骤中,我们将设置一个自托管的 GitHub runner。自托管 runner 是一个可以部署和管理来自 GitHub 网站上 GitHub Actions 任务执行的系统。与 GitHub 托管的 runner 相比,自托管 runner 的一个优势是灵活性。它提供了对操作系统、硬件和其他工具的更多控制,可以根据您所需的应用程序需求进行自定义。
自托管 runner 可以在不同级别添加,例如:
-
仓库级 runner,这些专用于单个仓库。
-
组织级 runner,这些可以处理组织中多个仓库的任务。
-
企业级 runner,可以分配给多个组织。
要继续,请通过 ssh 登录到您的服务器:
|
1 |
ssh username@server_ip |
使用以下命令切换到您的家目录:
|
1 |
cd ~ |
然后,创建一个名为 action-runners 的目录并进入其中:
|
1 |
mkdir actions-runner && cd actions-runner |
接下来,下载最新版本的 runner 软件包:
|
1 |
curl -o actions-runner-linux-x64-2.298.2.tar.gz -L https://github.com/actions/runner/releases/download/v2.298.2/actions-runner-linux-x64-2.298.2.tar.gz |
然后使用以下命令解压下载的软件包:
|
1 |
tar xzf ./actions-runner-linux-x64-2.298.2.tar.gz |
回到您的仓库,在 Settings 选项卡中,在左侧面板上点击 Actions,然后点击 Runners,就像我们在 Step 4.
中做的那样。您将看到列出的一个命令,其中包含一个将您的自托管 runner 链接到您的 GitHub 仓库的 token。在您解压 GitHub runner 代码的目录中,使用列出的命令来链接您的 runner,例如:
|
1 |
./config.sh --url https://github.com/EspiraMarvin/react-tut-test --token XXXXXXXXXXXXXXXXXXXXXXXXXXX |
它应该会验证成功:

按回车键选择默认(Default)runner 组。
然后为您的 runner 输入一个名称,例如 my-runner,然后按回车键。
按回车键跳过添加其他标签,您应该会看到下方截图中的成功消息:

输入您的工作目录名称,例如 react-cicd,它应该会成功并显示文本 settings saved.
最后,运行 ./run.sh,这应该会显示 Connected to Github:

但这不会在后台运行,如果我们在终端中输入 ctrl+c,runner 将会停止,我们需要将其替换为 .svc.sh 服务,以使 runner 作为服务持续运行,以便我们可以继续与其交互。
使用 ctrl+c 停止 runner。您可以通过运行以下命令来安装 .svc.sh 服务:
|
1 |
sudo ./svc.sh install |
安装完成后,使用以下命令启动服务:
|
1 |
sudo ./svc.sh start |
这应该会成功,并显示 active (running).
要确认 svc.sh 服务已启动并正在运行,请执行以下命令:
|
1 |
sudo ./svc/sh status |

此时,任何可能已排队等待自托管 runner 的工作流都应该成功运行。您也可以编辑文件并进行尝试。例如,修改 关于.tsx 文件,提交并推送更改,自托管 runner 将成功完成该任务。
步骤 6. 设置 Nginx 服务器块
在此步骤中,我们将在 Nginx 中设置一个服务器块,以查看我们 React 应用程序的构建版本。我们有一篇关于 设置 Nginx 服务器块 的教程,您可能会觉得很有帮助。
以下是本教程中使用的服务器块示例:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
server { listen 80; listen [::]:80; server_name react.test; root /var/www/react-cicd/build; index index.html index.htm index.nginx-debian.html; add_header X-Frame-Options "SAMEORIGIN"; add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options "nosniff"; charset utf-8; location / { try_files $uri $uri/ =404; } } |
您将在以下目录中创建一个 Nginx 服务器块配置文件: /etc/nginx/sites-available 目录。
使用以下命令,用 nano 编辑器打开一个文件来配置您网站的服务器块:
|
1 |
sudo nano /etc/nginx/sites-available/react-cicd |
复制上面共享的服务器块并根据您的目录路径进行修改,然后将其粘贴到打开的文件中。编辑完成后,按 ctrl+x 然后按 y 和 enter 保存并退出。
保存后,为以下服务器块配置创建一个符号链接: react-cicd 服务器块配置,从 /etc/nginx/sites-available 到 /etc/nginx/sites-enabled ,通过运行以下命令:
|
1 |
sudo ln -s /etc/nginx/sites-available/react-cicd /etc/nginx/sites-enabled/ |
要使更改生效,您需要重启 Nginx。但是,在重启 Nginx 服务之前,请通过运行以下命令来测试 Nginx 配置是否有效:
|
1 |
sudo nginx -t |
如果配置正确,测试应该会成功。
注意到服务器块中 server_name 指令的值为 “ react.test ” 吗?您需要将此值添加到本地计算机的 hosts 文件中。这将使您能够在浏览器中打开该应用程序。此步骤仅适用于本地开发环境中使用的虚拟域名。如果您有一个已注册的域名并链接到了服务器的公网 IP,那么该域名应该已经可以在浏览器中访问了。
在您的本地计算机上,使用以下命令打开 hosts 文件:
|
1 |
sudo nano /etc/hosts |
在 hosts 文件中,添加您服务器的 IP 地址,例如 127.0.0.1,后面紧跟您的虚拟域名。
示例如下所示。然后关闭文件并保存:
|
1 |
192.168.3.123 react.test |
回到您服务器的 /var/www 目录中,创建一个新目录,您可以通过运行以下命令将其命名为 react-cicd:
|
1 |
mkdir react-cicd |
在此阶段,我们将取消注释 node.js.yml 文件中的最后一条命令。
此命令将我们的 React 应用程序的构建文件夹从我们在上一个 步骤 5.
中指定的 actions-runner 目录内的工作文件夹复制,并将 public 文件夹放入 /var/www/react-cicd 目录中。
现在,服务器块可以访问我们的应用程序并将其显示在浏览器中。
最后,使用以下命令重启 Nginx 服务:
|
1 |
sudo service nginx restart |
现在,您可以在 关于.tsx 文件中进行更改,然后提交并将更改推送到您的仓库。构建成功后,您将在 http://react.test 或您指定的域名处看到 React 应用程序的构建版本。请避免编辑 href 元素,在 Home.tsx 文件中,因为这可能会导致已编写的测试失败。您仓库中的 Actions 选项卡也应该显示已完成的任务构建。

结论
使用 Github Actions 进行持续集成带来了许多优势,包括良好的开发人员体验、有助于持续测试、使大型团队中的协作更加轻松、缩短开发时间、快速发布新功能、实时反馈和客户满意度,从而使您在竞争对手中脱颖而出。为了巩固这些知识,您可能还想了解 在 Ubuntu 上设置 GitLab 持续集成 (CI) 流水线。以及使用 自托管 GitLab 实例 来托管您的 Docker 镜像并运行私有构建。
祝您计算愉快!
评论
暂无评论。发表第一条评论吧。