基于 Github + CircleCI 实现 Laravel 项目的持续集成


上篇教程学院君给大家介绍了持续集成的概念和意义,并就三个常见的持续集成系统进行了对比,以及在项目中如何选用,今天,我们就从最简单的 CircleCI 入手,结合 Github 代码仓库演示如何对前面开发的待办任务项目进行持续集成。

创建 Github 代码仓库

首先在 Github 中新建一个仓库用于保存待办任务项目代码,我们将其命名为 todoapp

创建完成后,将本地项目关联到该仓库并将代码提交上来:

git init
git add .
git commit -m 'first commit'
git remote add origin https://github.com/nonfu/todoapp.git
git push -u origin master

集成 CircleCI 到 Github 项目

接下来,我们要做的是将 CircleCI 集成到刚刚初始化的 Github 项目中来,以便在后续提交代码时通过 CircleCI 项目进行构建和测试。

在 Github 中集成 Circle 很简单,我们打开 GitHub Marketplace 页面,在搜索框中搜索 circleci,即可看到如下结果:

点击这个搜索结果进入 CircleCI 应用界面,可以看到这个 Github 应用支持 PHP 语言,点击「Set up a plan」按钮:

页面会跳到订阅计划选择区域,我们选择免费版本,该版本每月支持 1000 分钟构建时长,对于小型项目或测试项目也足够了:

点击「Install it for free」按钮进行安装,页面会跳转到确认及授权页面,我们一路点击绿色按钮即可:

授权成功后,页面跳转到 CircleCI 页面,在 Github 中授权集成 Circle 应用时,实际上也会在 CircleCI 系统注册一个与 Github 账户关联的新账号,这样,我们就可以访问 Github 上自己的代码仓库,这里选择刚刚创建的 todoapp 仓库与 CircleCI 集成:

点击「Follow」按钮,即可完成 CircleCI 与 Github 仓库的关联,当前我们还没有在代码仓库中配置 CircleCI 配置文件,所以在 CircleCI 的作业列表里,还不能进行任何构建操作。

回到 Github todoapp 代码仓库,在 Settings->Webhooks 列表里也可以看到该项目已经与 CircleCI 关联:

点击「Edit」按钮对这个 Webhook 进行编辑,我们勾选只有在 push 代码到仓库事件发生时才会通知 CircleCI 系统根据项目里的 Circle 配置文件对项目进行构建和测试:

编写 CircleCI 配置文件

完成 CircleCI 与 Github 代码仓库的关联后,我们就可以回到本地项目来配置 CircleCI 配置文件了,CircleCI 会根据这个 YAML 配置文件执行构建和测试工作。

准备 .env.testing 环境配置

首先我们拷贝一个用于测试环境的环境配置文件 .env.testing

cp .env.example .env.testing

修改 .env.testing 如下几个配置项:

APP_ENV=testing
APP_URL=http://127.0.0.1:8000

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=todoapp
DB_USERNAME=root
DB_PASSWORD=

创建 .circleci/config.yml

然后在项目根目录下创建一个 .circleci 目录,并在该目录下新建一个 config.yml 配置文件:

mkdir .circleci
cd .circleci
touch config.yml

CircleCI 默认会读取 .circleci/config.yml 配置文件来初始化测试环境并进行项目构建、编译和测试(具体操作由开发者决定) 工作,如果项目中不包含这个配置文件,则 CircleCI 会初始化失败。

开始前的一些约定

由于对项目进行构建和测试是需要一定的基础设施的,比如需要 PHP 环境、Composer、NPM,如果涉及到数据库操作还要安装对应的数据库软件和 PHP 驱动,好在我们在上一篇介绍 CircleCI 的时候提到它支持基于 Docker 环境来运行构建和测试,并且 CircleCI 官方也提供了很多 Docker 镜像,我们可以基于这些镜像来初始化构建和测试需要的软件环境。此外,对于 HTTP 测试和浏览器测试还需要项目可以基于 Web 进行访问,对于这一块,我们可以通过 Laravel 框架内置的 PHP Web 服务器来提供支持,以保持环境的轻量化。

有了这些预备知识,下面我们就可以按照 CircleCI 对配置文件的格式要求来编写 YAML 配置文件了。

编写 config.yml 配置文件

学院君为本项目编写的最终 .cirecleci/config.yml 配置文件内容如下:

version: 2

jobs:
  build:
    docker:
      - image: circleci/php:7.1-node-browsers
        environment:
            MYSQL_HOST: 127.0.0.1
            MYSQL_DB: todoapp
            MYSQL_USER: root
            MYSQL_ALLOW_EMPTY_PASSWORD: true
            MYSQL_PASSWORD:
      - image: mysql:5.7
        command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --innodb-large-prefix=true --innodb-file-format=Barracuda
        environment:
            MYSQL_USER: root
            MYSQL_ALLOW_EMPTY_PASSWORD: true

    working_directory: ~/todoapp

    steps:
      - checkout
      - run: sudo apt install -y libsqlite3-dev zlib1g-dev
      - run: sudo apt install -y mysql-client
      - run: sudo docker-php-ext-install zip
      - run: sudo docker-php-ext-install pdo_mysql
      - run: sudo composer self-update
      - restore_cache:
          keys:
              - composer-v1-{{ checksum "composer.lock" }}
              - composer-v1-
      - run: mv .env.testing .env
      - run: composer install -n --ignore-platform-reqs
      - save_cache:
          key: composer-v1-{{ checksum "composer.lock" }}
          paths:
              - vendor
      - restore_cache: # special step to restore the dependency cache if `package.json` does not change
          keys:
              - node-v1-{{ checksum "package.json" }}
              # fallback to using the latest cache if no exact match is found (See https://circleci.com/docs/2.0/caching/)
              - node-v1-
      - run: npm install
      - save_cache: # special step to save the dependency cache with the `package.json` cache key template
          key: node-v1-{{ checksum "package.json" }}
          paths:
              - node_modules
      - run: npm run production
      - run:
          name: Mysql database
          command: mysql -h 127.0.0.1 -u root -e "create database todoapp;"
      - run: php artisan key:generate
      - run: php artisan migrate
      - run: php artisan passport:install
      - run:
          name: Run Laravel Server
          command: php artisan serve
          background: true
      - run: vendor/bin/phpunit
      - run:
          name: Start Chrome Driver
          command: ./vendor/laravel/dusk/bin/chromedriver-linux
          background: true
      - run:
          name: Run Laravel Dusk Tests
          command: php artisan dusk

在这个配置文件里,我使用了 circleci/php:7.1-node-browsersmysql:5.7 这两个 Docker 镜像用来提供软件环境支持,前者主要提供了 PHP 及 Node.js 相关环境,后者主要用于提供 MySQL 数据库,并且还初始化了数据库连接信息配置。

接下来,通过 working_directory 配置项指定 CircleCI 构建和测试所在项目目录,这里和代码仓库名称保持一致即可。

最后就是通过 steps 配置构建和测试的所有步骤:

  • 首先通过 checkout 检出仓库镜像和代码
  • 然后安装额外需要的软件,比如 MySQL 客户端和对应的 PHP 扩展
  • .env.testing 重命名为 .env
  • 通过 Composer 安装项目必须的 PHP 依赖
  • 通过 NPM 安装前端依赖,然后运行 npm run production 编译前端资源
  • 在 MySQL 中创建 todoapp 数据库
  • Laravel 项目初始化
  • 运行 php artisan serve 启用 PHP 内置的 Web 服务器
  • 运行 phpunit 执行 HTTP 测试用例
  • 启动 ChromeDriver,通过 php artisan dusk 执行浏览器测试用例

首次提交代码进行持续集成

接下来,我们可以将本地开发分支代码提交到仓库,当 push 事件发生时,Github 会发送 Webhook 请求到 CircleCI,CircleCI 根据项目中的 .circleci/config.yml 配置文件初始化环境并对项目进行构建和测试,这个请求是异步进行的,这种设计也比较合理,因为环境初始化、构建和测试都比较耗时。

创建新分支并提交代码

下面我们来演示下这个操作流程,首先在本地项目根目下检出一个新的开发分支 dev-branch

git checkout -b dev-branch

然后为项目添加一个 README.md 文件,并在该文件中添加文本「A TDD Demo App For Laravel By Laravel 学院」:

echo "A TDD Demo App For Laravel By Laravel 学院" >> README.md

然后将变更提交到仓库并 push 到 Github:

git add .
git commit -m 'test circleci'
git push --set-upstream origin dev-branch

查看 CircleCI 构建测试结果

在浏览器中进入 Github 仓库页面,在代码 commits 记录中将分支切换到 dev-branch,可以看到提交记录右侧有一个黄色的圆点,表明 CircleCI 正在构建测试中,如果构建测试成功,则该图标变成绿色的勾,如果构建测试失败,则该图标变成红色的叉,点击该图标,就可以通过「Details」链接进入 CircleCI 作业页面:

在 CircleCI 作业页面,可以看到每一个构建测试步骤及相应细节,每个步骤的执行都遵循 .circleci/config.xml 配置文件中的配置:

如果某个步骤出错,则不会再继续后面的构建和测试,会告知错误明细然后给用户发送邮件通知,测试结果也会同步到 Github 的代码提交记录那里:

合并代码到主干及后续优化

如果 CircleCI 构建测试成功,则可以将开发分支代码合并到主干:

git checkout master
git merge dev-branch

否则需要修改问题然后继续提交,直到构建测试通过。将 CircleCI 持续集成系统集成到代码提交合并流程的好处是可以将构建和测试过程流程化,并且保证每次合并到主干的代码都是测试通过的(假定测试代码覆盖所有业务逻辑并且有效)没有问题的代码。

如果是私有仓库的话,你还可以尝试将自动部署及合并代码到主干的流程添加到 CircleCI 的 YAML 配置中,从而实现从构建、编译(前端资源)、测试和部署整体流程的自动化。


点赞 取消点赞 收藏 取消收藏

<< 上一篇: 持续集成的定义和常用 CI 系统对比

>> 下一篇: 基于 Github + Travis CI 实现 Laravel 项目的持续集成