阅读本文大概需要 19 分钟。

前段时间我更新了我的分布式爬虫管理框架—— Gerapy(话都说到这儿了打个广告,跟繁琐的命令行说拜拜!Gerapy分布式爬虫管理框架来袭!,哇,哇,就是,哇!)

现在 DevOps 的理念可谓是相当火,其中 CI/CD(持续集成、持续部署)是必不可少的环节。有了它们,我们开发完软件之后,一些测试、构建、部署的环节就可以自动化完成了。

我开发的的这款分布式爬虫管理框架—— Gerapy,代码也是放在了 GitHub 上面,但在之前 GitHub 上面是缺少原生的 CI/CD 功能支持的,可能需要根据第三工具或者 Webhook 等来配合实现项目的自动测试、构建和部署。

比如我可能有这么一些需求:

•每次合并代码到 master 分支时,想测试这个项目能否在各个版本的 Python 环境下正常安装和运行。•我为 Gerapy 新建了一个独立的 Repo,叫做 Gerapy/Gerapy,在 docs 文件夹下存放文档说明,但我还另外新建了一个 Repo 专门用来存放文档,叫做 Gerapy/Docs,希望能把 Gerapy/Gerapy 的 docs 子文件夹下的内容整个自动同步到 Gerapy/Docs 这个 Repo 的根目录。•每次 Gerapy 发布新版本的时候,自动构建 Docker 镜像,并上传到 Docker Hub,打上 latest 标签和版本号标签。•每次 master 分支提交代码的时候,自动构建 Docker 镜像,并上传到 Docker Hub,打上 master 标签,代表当前 master 分支版本。

上面的功能之前有一部分工作是手工操作的,有一部分是借助于第三方工具来自动操作的,感觉并不是一个很好的解决方案

在最近一段时间,GitHub 上面上线了 Actions 功能,它就是为 CI/CD 而生的,和 GitHub 项目原生紧密结合。然而几个月以来一直处于内测阶段。就在 11 月 13 日,GitHub Actions 功能正式上线了。

上线之后,我就开始正式使用这个功能了,是真的香!

上面的四个需求,我用 GitHub Actions 已经完全实现了自动化,非常简单方便。

接下来简单介绍下我的一些实现方式。

GitHub Actions

首先简单介绍下 GitHub Actions,其官方介绍页面为:https://github.com/features/actions,介绍语如下:

Automate your workflow from idea to production. GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want.

简而言之就是提供了一个高效易用的 CI/CD 工作流,帮助我们自动构建、测试、部署我们的代码。

另外它支持三大平台—— Linux、MacOS、Windows,支持任何编程语言,而且官方提供了许许多多的 Actions 库供我们直接使用,帮助我们更快地搭建工作流。

GitHub Actions 的官方文档可以见:https://help.github.com/en/actions/automating-your-workflow-with-github-actions,如果大家想好好研究下的话,一定要好好看看。

下面我就介绍我使用 GitHub Actions 实现上文所述的四个需求的方法。

自动测试

由于我开发的 Gerapy 是一个 Python Package,因此我看重的是测试它是否可以在各个 Python 平台下安装和正常使用,于是我新建了一个 GitHub Action,它会自动在项目目录下生成一个 .github/workflows/*.yml 文件,内容如下:

name: buildon:   push:    branches:     - master    - devjobs:  test:    runs-on:     - ubuntu-latest    strategy:      max-parallel: 3      matrix:        python-version: [3.5, 3.6, 3.7]    steps:    - uses: actions/checkout@v1    - name: Set up Python ${{ matrix.python-version }}      uses: actions/setup-python@v1      with:        python-version: ${{ matrix.python-version }}    - name: Install Dependencies      run: |        python -m pip install --upgrade pip        pip install .    - name: Run Gerapy      run: |        gerapy -v        gerapy init        cd gerapy        gerapy migrate        gerapy initadmin

其实在这里一个 Action 就是一个 YAML 文件,其后缀为 yml,它规定了一系列语法规则,我们根据它的语法规则写出一些工作流,在符合一定条件时,这些工作流会被触发,自动执行。

比如这里最开头,on 就是监听某个事件,其内容为 push,意思就是当 push 代码的时候,就会触发。再进一步地,这里定义了两个分支 master 和 dev。这什么意思呢?就是当我往 master 或者 dev 分支 push 代码的时候,我们定义的工作流就会执行。

下面的 jobs 就是工作流的定义了,包括在什么平台运行,具体执行什么步骤。

比如这里 runs-on 我就定义了在 ubuntu-latest 版本上运行,另外定义了一些并行策略和参数,比如这里就定义了 Python 的三个版本参数,在 3.5、3.6、3.7 版本上运行。

下面的 steps 就是具体执行哪些步骤了。第一步和第二步,我们可以看到它都有一个 uses 参数,内容都为 actions 开头,这就说明我们使用了 GitHub 提供的写好的 Action,我们只需要引用它的名字就能使用了。这两步运行完毕之后,Python 环境会被初始化,同时会从 GitHub Clone Gerapy 项目代码到本地。

在第三步和第四步,就是我自定义的 Task 了,这里自持直接写入 Shell 脚本。在这里我分了两步。

第三步 Install Dependencies 就是安装 pip 和 Gerapy 安装包,其中一句 pip install . 就是安装当前 Gerapy 目录下的内容到系统中,安装完成之后,就可以使用 gerapy 命令了。

于是第四步 Run Gerapy 就是测试了 gerapy 命令的一些初始化使用,包括初始化工作环境、数据库迁移、初始化账号等等,当然还有更多,比如运行某些测试,运行服务等等,这里我只把一些必要的内容写进去了。

好,基本内容就是这样。

保存这个 Action,命名为 build.yml,它会保存为 .github/workflows/build.yml 文件。同时在保存的时候,我们就相当于执行了一次 Push 任务,这时候我们就可以看到这个 Action 已经启动了,页面如下:

我们所定义的每一个步骤以及对应的执行结果都会显示在控制台中,一目了然。

可以看到这里初始化了三个版本的 Python 环境,同时都运行了其中的测试流程。如果测试成功,会打绿色的勾,如果失败,会提示红色的叉,并有邮件提示。

这样以来,一些自动化的测试就完成了!!!

同步文档到新的 Repo

接下来我这个需求可以说稍微有点奇葩了。

写项目免不了的要写文档,这里文档我是用 Sphinx 来写的,可以借助于 ReadTheDocs 自动构建并分发到 readthedocs.io 上面,类似这样子:

但文档的源代码我是放在了 Gerapy/Gerapy 这个 Repo 的 docs 文件夹,向 Scrapy 看齐,是这样子的:

但我想着还新建一个 Repo,来单独存放文档,比如我新建一个 Gerapy/Docs 这个 Repo,我在 Gerapy/Gerapy docs 子文件夹下的内容可以被自动同步到 Gerapy/Docs 根目录下面,这样我只需要往 Gerapy/Gerapy 上面提交代码,docs 子文件夹下面的内容变了,Gerapy/Docs 下面的内容也会跟着变。

那这个能不能做到呢?能!(我问你答,快乐神仙;自问自答,法力无边~~

这个流程可以分为四步:

•下载 Gerapy/Gerapy Repo 的源代码。•利用 git 的 subtree 命令将 docs 文件夹下的内容分离到新的分支。•将新分离的分支推送到 Docs 这个 Repo 下面。•推送 Docs 这个 Repo 到远程 Gerapy/Docs Repo。

这里面就有一个关键地方,那就是怎样无需密码将内容推送到远程 Gerapy/Docs 这个 Repo 下面,当然就是 SSH 了。(啊,超爽der)

那 SSH 的话应该怎么设置呢?我们首先要有一对公钥和私钥,这个我们用 ssh-keygen 命令自己生成就好了。

那接下来 Gerapy/Docs 里面需要存有公钥,怎么办呢?我们可以借助于 GitHub 提供的 Deploy Key 配置好公钥即可:

然后我们需要将私钥上传到 Action 所运行的虚拟机里面,但我们又不能明文将其放在 yml 文件里面,那这个怎么做到呢?只需要将其配置到 Secrets 里面即可,Action 是有权限访问到的:

嗯,做好这两部分工作之后,接下来完善一下 yml 文件就好了,内容如下:

name: sync docson:   push:    branches:     - masterjobs:  sync:    runs-on: ubuntu-latest    steps:    - name: Set SSH Environment      env:        DOCS_DEPLOY_KEY: ${{ secrets.DOCS_DEPLOY_KEY }}      run: |        mkdir -p ~/.ssh/        echo "$DOCS_DEPLOY_KEY" > ~/.ssh/id_rsa        chmod 600 ~/.ssh/id_rsa        ssh-keyscan github.com > ~/.ssh/known_hosts        chmod 700 ~/.ssh && chmod 600 ~/.ssh/*        git config --global user.email "cqc@cuiqingcai.com"        git config --global user.name "Germey"    - name: Sync Docs of Gerapy      run: |        cd /tmp        git clone git@github.com:Gerapy/Docs.git docs        cd docs        git branch -D docs || true        git push origin --delete docs || true        git clone https://github.com/Gerapy/Gerapy.git gerapy        cd gerapy        git subtree split --prefix=docs --squash -b docs        git checkout docs        git push /tmp/docs docs:docs        cd /tmp/docs        git checkout docs        git checkout -b master || git checkout master || true        git reset --hard docs        git push origin master --force

可以看到,这里主要就分了两步。

第一部分就是设置虚拟机的 SSH 环境,这里 secrets.DOCS_DEPLOY_KEY 就是我们刚才在 Secrets 里面定义的私钥,对应的运行命令就是将私钥添加到 ~/.ssh/id_rsa 里面。

第二部分就是分离 docs 文件夹到新的分支,然后将其上传到新的 Repo 下了。

那么这里有两条比较关键的命令:

git subtree split --prefix=docs --squash -b docs

这条命令就是将 docs 文件夹的内容分离到一个新的分支的根目录下,新的分支的名称为 docs。

git push /tmp/docs docs:docs

这条命令就是将本地的分支推送到另外一个本地 Repo 下,注意这里 push 的目标不一定是远端的 Repo 地址,也可以是本地的 Repo 地址。

最后,将新的 Repo 内容强制推送到远程即可。

这样我们就可以实现,Gerapy/Gerapy Repo docs 文件夹下内容的变动,会自动更新到 Gerapy/Docs Repo 了。

例如 docs 下是这样的:

Gerapy/Docs Repo 下和子文件的内容会一直维持同步,并在 master 分支上面:

自动构建 Docker 镜像

由于 Gerapy 是一个 Web 工程,所以它非常适合于打包一个 Docker 镜像。对于 Docker 的镜像,我期望有三个版本:

•当前 master 分支的版本,比较稳定,但未发布版本。•最新版本,latest,代表最新的发布版本。•每个历史版本,每次发布版本的版本号,都标记一个 tag。

最后我们自动构建的镜像都自动 Push 到 Docker Hub 上面,这样大家都可以使用了。

那这个怎么做到呢,同样借助于 GitHub Action 也可以轻松做到。

首先 master 版本,由于没有发版,所以前端需要自行 build,然后 Python Package 需要安装本地代码。废话不多说了,上代码:

name: build docker image masteron:  push:    branches:     - master    paths:    - .github/workflows/**    - gerapy/**jobs:  build:    runs-on: ubuntu-latest    steps:    - name: Checkout Source      uses: actions/checkout@v1    - name: Docker Login      run: docker login -u germey -p ${{ secrets.DOCKERHUB_LOGIN_PASSWORD }}    - name: Setup Node.js      uses: actions/setup-node@v1.1.0      with:        version: 10.x    - name: Build Frontend Source      run: |        cd gerapy/client        npm install        npm run build    - name: Build the Docker Image      run: |        docker build -t germey/gerapy:master -f ./docker/Dockerfile .    - name: Push the Docker Image      run: docker push germey/gerapy:master

可以看到这里,监听了 master 分支的变动,同时限定了路径 workflows 文件夹和 gerapy 文件夹下变动。

流程包括了前端的构建和 Docker 的打包,Docker 打包的时候使用了 -f 命令指定了 Dockerfile 的路径,并将打包完成之后的镜像标记为 gerapy:master,推送到 Docker Hub 即可。

对于发布新版本的时候,则直接监听 tag 的变动即可:

name: build docker image releaseon:  push:    tags:      - 'v*.*.*'jobs:  build:    runs-on: ubuntu-latest    steps:    - name: Checkout Source      uses: actions/checkout@v1    - name: Docker Login      run: docker login -u germey -p ${{ secrets.DOCKERHUB_LOGIN_PASSWORD }}    - name: Setup Node.js      uses: actions/setup-node@v1.1.0      with:        version: 10.x    - name: Build Frontend Source      run: |        cd gerapy/client        npm install        npm run build    - name: Build and Push the Docker Image      run: |        tag=${GITHUB_REF:11}        echo "Build Tag '$tag'"        docker build -t germey/gerapy:$tag -f ./docker/Dockerfile .        docker push germey/gerapy:$tag        regex='^([0-9]+\.){0,2}(\*|[0-9]+)$'        if [[ $tag =~ $regex ]]; then          echo "Build Stable Version '$tag'"          docker tag germey/gerapy:$tag germey/gerapy:latest          docker push germey/gerapy:latest        fi

可以看到这里监听的配置改成了 tags,tag 也变成了一个变量,可以通过 ${GITHUB_REF:11} 获取到。

同时这里还加了一个正则判断是不是正式的发版,如果是 beta、rc 版本,则不构建正式 latest 的 Docker 镜像。

最后我们看看我再一次发版之后,构建完成之后,Docker Hub 的效果:

可以看到,我发布了 0.9.2 版本之后,它就自动构建了 0.9.2 版本的镜像,同时将 latest 镜像指向 0.9.2 版本。另外对应 maser 版本也构建了一个版本。

这样,以后妈妈再也不用担心我忘记打 Docker 镜像啦。

以上便是我将 GitHub Actions 应用到我的开源项目上的记录。

最后,如果大家对 Scrapy 爬虫感兴趣的话,也(非常)欢迎大家(高高兴兴的)了解一下我写的 Gerapy 框架,利用它我们可以(无敌)更方便地管理(呀)、监控(呀)、(或者是)部署 Scrapy 爬虫项目(什么的)。

其 GitHub 地址为:https://github.com/Gerapy/Gerapy,文档:https://docs.gerapy.com/。

好文和朋友一起看~

GitHub Actions,卧槽!牛批!相关推荐

  1. Github Actions:再次改变软件开发

    本文转自 FEPulse 公众号(微信搜索 FEPulse,精选国内外最新前端资讯,为你把握前端脉搏). Github Actions 是 GitHub Universe 大会上发布的,被 Githu ...

  2. 利用Github Actions部署自动更新PaddleOCR指定代码到指定仓库

    目录 引言 需求描述 解决方法 采用Github Actions功能 具体代码 总结 参考资料 引言 首先说呢,我也不想重复造轮子, 但是无奈,网上博客看了一大圈,却始终没有找到自己需要的东西 需求描 ...

  3. springboot做网站_Github点赞接近100k的SpringBoot学习教程+实战推荐!牛批!

    如果觉得看完文章对你有帮助记得点个赞,不要做收藏党.丢进收藏夹吃灰哦! 很明显的一个现象,除了一些老项目,现在 Java 后端项目基本都是基于 Spring Boot 进行开发,毕竟它这么好用以及天然 ...

  4. 如何能在git bash中使用mvn命令_使用Github Actions完成CI/CD工作

    在本文中,我们将介绍如何使用 Github Actions 自动化开发部署工作流,使版本控制和 CI/CD 平台在同一个地方完成. 自2019年开始,github便提供了CI/CD工具,对于publi ...

  5. GitHub之GitHub Actions的项目自动化持续集成和部署

    一.基本概念 GitHub Actions 是一个由事件驱动的自动化平台,通过设置触发条件,在某些事件发生时自动运行指定的操作.换言之,GitHub Actions 不仅允许开发人员在平台上托管代码, ...

  6. Gitee 如何自动部署博客 Pages?推荐用这个GitHub Actions!

    大家好,我是若川.最近组织了源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列> ...

  7. 使用 Github Actions artifact 在 workflow job 之间共享数据

    AgileConfig 在使用 react 编写UI后,变成了一个彻彻底底的前后端分离的项目,上一次解决了把react spa 跟asp.net core 站点集成起来ASP.NET Core 集成 ...

  8. 通过 GitHub Actions 自动创建 Github Release

    通过 GitHub Actions 自动创建 Github Release Intro 在 GitHub 上维护了几个小的开源项目,每次在发布新版本的时候会创建一个 release,这样可以比较方便的 ...

  9. GitHub Actions 支持 skip ci 了

    GitHub Actions 支持 "skip ci" 了 Intro GitHub Actions 作为 GitHub 官方的 CI 支持,很多开源项目已经在使用 Actions ...

最新文章

  1. 如何在window下杀死进程?
  2. python 生成随机数_python 生成随机数模块random 常用方法总结
  3. linux8重启服务代码,linux(centos8):安装分布式事务服务seata(seata 1.3.0/centos 8.2)
  4. 签约沈腾,易车开启三年品牌计划,穿越车市寒冬
  5. JVM系列五:垃圾回收器
  6. Android从assets和res中读取文件
  7. Servlet 2.4 规范之第四篇:Servlet上下文
  8. 在64位系统中无法看到Microsoft Excel Application的问题
  9. DNF2020年全新脚本展示第三部分
  10. 使用Nodejs+puppeteer 批量保存网页为图片或PDF
  11. java系统过载保护_过载保护之常见过载处理
  12. Mixpanel获Andreessen Horowitz投资 为Viddy及Path提供分析服务
  13. html怎么定义403页面,自定义 403 错误页面(示例代码)
  14. unity抛物线_发射弓箭轨迹的实现
  15. UG NX 12 抽取几何特征
  16. java基于ssm的自助旅游管理系统
  17. 数据中台架构与技术选型
  18. (附源码)计算机毕业设计Java二次元文化网站
  19. 02.虚拟功能介绍虚拟机网络配置xshell远程连接
  20. 第22期状元简讯:支付宝母公司斥资11.8亿元控股天弘基金

热门文章

  1. NSValue包装自定义结构体
  2. 超链接禁用_如何在Microsoft Word中禁用超链接
  3. nest 架构_如何与其他人分享您的Nest Cam Feed
  4. 如何解决90%的报表设计难题?300张报表模板任君挑选
  5. 城市智慧停车系统方案的产品设计体系介绍
  6. 【20181026T2】**图【最小瓶颈路+非旋Treap+启发式合并】
  7. PHP 基础篇 - PHP 中 DES 加解密详解
  8. 避免活跃性危险(第十章)
  9. 算法笔记_226:填符号凑算式(Java)
  10. Mybatis——返回类型为 集合嵌套集合 应该如何处理