GitHub Actions初体验

1,495 阅读9分钟

什么是GitHub Actions

GitHub Actions 是 GitHub 的CI/CD服务,于2018年10月推出

这里可能不是所有的小伙伴都理解CI/CD。我们稍微照顾一下不知道的小伙伴, 简单的介绍一下CI/CD。

什么是CI/CD?

它所要解决的问题

主要解决在集成新代码时所引发的一些问题

集成地狱是指交付团队中的成员集成其各自的代码时的生产点。在传统的软件开发环境中,这种集成过程很少是平滑且无缝的,而是需要花费数小时甚至数天的时间来修复代码,以便最终进行集成。持续集成(CI)旨在通过鼓励和鼓励团队成员进行频繁集成(例如每小时或至少每天一次)来完全避免这种情况

目标群体

它是针对开发,质量和运营团队的一种解决方案

它由三个核心概念组成

  • Continuous integration
  • Continuous delivery
  • Continuous deployment

CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。这些关联的事务通常被统称为“CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。

到这里大家对CI/CD已经有个一个初步的认识

简单总结一下:

CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法

CI/CD 既可能仅指持续集成和持续交付构成的关联环节,也可以指持续集成、持续交付和持续部署这三项构成的关联环节。更为复杂的是,有时“持续交付”也包含了持续部署流程。

归根结底,我们没必要死扣这些定义,只需记得 CI/CD 其实就是一个流程或者管道,用于实现应用开发中的高度持续自动化和持续监控。因案例而异,该术语的具体含义取决于 CI/CD 管道的自动化程度。许多企业最开始先添加 CI,然后逐步实现交付和部署的自动化(例如作为云原生应用的一部分)

  • 持续集成(Continuous integration 简称: CI)
概念: 一天多次或者频繁的将代码集成到主干
目的: 可以让产品快速迭代,还能保证质量
采用的方式: 在集成到主干之前必须要通过自动化测试和各种依赖安装正常
误解:持续集成并不能消除Bug,而是让它们非常容易发现和改正

持续集成偏重点在于开发人员提交了新代码之后,会立刻进行构建, 单元测试等操作。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。

  • 持续交付(Continuous delivery 简称: CD)
概念: 频繁地将软件的新版本,交付给质量团队或者用户,以供评审

持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」production-like environments中。比如,我们完成单元测试后,可以把代码部署到连接数据库的 Staging 环境中更多的测试。如果代码没有问题,可以继续手动部署到生产环境中。

  • 持续部署(Continuous deployment)
概念: 指的是代码通过评审以后,自动部署到生产环境

它是持续交付的下一步

最后用几张图来加深一下对各个概念的理解

持续集成

持续交付

持续部署

学会一个技能其实并不会让我们非常开心, 而是拿它做出点什么后,才会更加由成就感。

这是我的一个主观感受,不知道你们是不是也有同感。

现在让我们回到 GitHub Actions这里来,现在我们已经比较清楚的知道它什么样的一个服务,也知道了它能帮我解决什么样的问题。那么接下来,我需要自己搞一点事情,然后让它帮我们解决,以此来让我们学会如何使用GitHub Actions

需求的产生

当我们对GitHub Actions有了基本认识后。 那么我们该如何使用它来辅助我们呢?

要想让一个任务有始有终,就必须先要确定任务的边界,也就是确切的需求。

需求的产生又是源于我们对事物的思考。

目前针对Android端经过我的思考🤔,我提出了3点可以改进的地方:

  • 每次给测试人员发包 都是需要我先在本地打测试包,然后通过slack或者微信分发到指定的测试群中 (由手动 --> 自动化)
  • 每次测试人员确认测试没有问题后,我都需要将正式包分发给指定的人,上传至正式的分发渠道或者商店 (正式包分发(通知和原始文件) 由手动 --> 自动化)
  • 每次分发完成后,合并到master后需要将目前的代码打包存档 (由手动 --> 自动化)

目前暂定为 通知统一采用slack的指定channel,

依赖环境的确认, 命令打包, 和软件通信(Message, File)

针对上述需求,作为开发人员需要找到一个解决方案(给自己找一个光明正大使用GitHub Actions的理由)

可行性

Jenkins和Strider是开源软件,需要服务器资源支持

Travis和Codeship对于开源项目可以免费使用,不能用于私有项目

经过不断的搜索, GitHub Actions 进入了我的视野

它不要单独的部署服务器,由GitHub官方出品, 对于私有项目,提供了一定的限制支持

价格方面

那么作为这么一个CI/CD界的新秀它有什么特点呢?

GitHub Action的特色

大家知道,持续集成由很多操作组成,比如切换分支,拉取代码、运行测试用例、登录远程服务器、发布到第三方服务等等。

GitHub Actions把这些操作就称为 actions

我们这里可以将每个action比喻成一个函数, 既然是函数那就一定具有复用性。

很多操作在不同项目里面是类似的功能,那么就完全可以复用。GitHub就注意到了这一点,想出了一个很妙的点子,允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用。

如果你需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可,整个持续集成过程,就变成了一个 actions 的组合。这就是 GitHub Actions 最特别的地方。

下面都是合法调用action的方式

actions/setup-node@74bc508 # 指向一个 commit
actions/setup-node@v1.0    # 指向一个标签
actions/setup-node@master  # 指向一个分支

还有非常不错的学习资源:

有点类似 Faas 服务的概念,可操作的粒度更加的细小

下面我们就介绍一些基本的概念

基本概念

基础术语

workflow(工作流): 持续集成的一次运行的过程就是一个 workflow

job(任务): 一个workflow由一个或多个 job构成,含义是一次持续集成的运行可以完成多个任务

step(步骤):每个 job 由多个 step 构成,一步步完成

action(动作):每个 step 可以依次执行一个或多个action

拿一个项目是否可以包含多个 workflow 呢?

层级关系图

workflow文件格式

workflow 文件采用 YAML 格式

在项目中会生成一个 .github/workflows的一个隐藏文件夹, 文件夹下会有以 yml/yaml 结尾的文件

我拿官方的Demo来进行简单的分析

下面针对每个知识点 我们在详细的介绍一下,来加深印象

几种事件的出发方式:

当master和release/* 分支被push代码的时候,启动工作流

on:
  push:
    branches:
    - master
    - release/*

当拉取代码的时候触发事件

on:
  pull_request:
    branches:
    - master

每周的周一至周五2点触发

on:
  schedule:
  - cron: "0 2 * * 1-5"

有的小伙伴可能会问,除了常用的linux系统还支持其他操作系统呢。 答案显然是肯定的

目前官方所有支持的虚拟系统

  • ubuntu-latest, ubuntu-18.04, or ubuntu-16.04
  • windows-latest or windows-2019
  • macos-latest or macos-10.15

job之间的依赖

语法格式如下

jobs:
  job1:
  job2:
    needs: job1

携带参数

action携带参数

- name: Setup Node
  uses: actions/setup-node@v1
  with:
    node-version: '10.x'

条件运行

根据条件判断是否运行 steps 或者 jobs

这个例子展示了如有触发事件是push时才能运行这个脚本

steps:
- run: npm publish
  if: github.event == 'push'
- run: npm build
  if: success()  
- run: npm 
  

矩阵运行

这个矩阵策略就是 分别在三个系统上 按照三个node版本进行运行

jobs:
  test:
    name: Test on node ${{ matrix.node_version }} and ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        node_version: ['8', '10', '12']
        os: [ubuntu-latest, windows-latest, macOS-latest]


    steps:
    - uses: actions/checkout@v1
    - name: Use Node.js ${{ matrix.node_version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node_version }}


    - name: npm install, build and test
      run: |
        npm install
        npm run build --if-present
        npm tes

测试截图

有了上面这些基础知识,我们就可以开始真正的做点儿事情了

实例展示

下面就是我要将刚刚的需求进行实现的一个过程:

实现需要的两个基础模块: 消息的分发 和 打包存档

       

临时存储

这些是您可能想要上传的一些常见构建和测试输出构件

  • 日志文件和核心转储文件
  • 测试结果、失败和屏幕截图
  • 二进制或存档文件
  • 压力测试性能输出和代码覆盖结果

您必须在工作流程运行时上传构件。 GitHub 提供两项可用于上传和下载构建构件的操作。 上传到工作流程运行的文件将使用 .zip 格式存档。 更多信息请参阅 action/upload-artifactdownload-artifact 操作.

在工作流程中作业之间传递数据

SlackBot支持

先创建一个SlackBot用于消息分发

开始配置这个机器人

增加相应的权限

在github内授权可以调用Slack Api

配置作用域


第一步创建一个 workflow

第二步建立工程项目和workflow文件 workflow.yml文件具体内容如下

我拆分来两个工作流  android_master.yml 和 android.yml

name: Android CI Master
on:
  push:
    branches: [ master ]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: setup jdk8
      uses: actions/setup-java@v1
      with:
        java-version: 1.8
    - name: build apk file
      run: ./gradlew assembleDebug
    - name: Upload APK
      uses: actions/upload-artifact@v1
      with:
        name: app
        path: app/build/outputs/apk/debug/app-debug.apk
    - name: Determine tag
      id: time
      run: echo "::set-output name=tag::$(date "+%Y.%m.%d")"
    - name: Read CHANGELOG
      id: changelog
      run: |
        echo "::set-output name=body::$(cat CHANGELOG.md)"
    - name: Version
      id: version
      run: |
        echo "::set-output name=version::$(cat VERSION.md)"
    - name: create Release
      id: create_release
      uses: actions/create-release@latest
      env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
         tag_name: ${{ steps.version.outputs.version }}
         release_name: ${{ steps.time.outputs.tag }}
         body: ${{ github.event.commits[0].message }}
         draft: false
         prerelease: false
    - name: Upload Release Asset
      id: upload-release-asset
      uses: actions/upload-release-asset@v1
      env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
         upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which i$
         asset_path: ./app/build/outputs/apk/debug/app-debug.apk
         asset_name: EnterpriseRelease-${{ steps.version.outputs.version }}.apk
         asset_content_type: application/zip

这里包含基本的编译和通知功能

name: Android CI Dev
on:
  push:
    branches: [ dev ]
jobs:
  slack-notifications:
    runs-on: ubuntu-latest
    name: Upload test file
    steps:
      - uses: actions/checkout@v2
      - name: setup jdk8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8
      - name: build apk file
        run: ./gradlew assembleDebug
      - name: Send message to Slack
        uses: archive/github-actions-slack@master
        with:
          slack-bot-user-oauth-access-token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }}
          slack-channel: test
          slack-text: ${{ github.event.commits[0].message }} 🤓
      - name: Result from "Send Message"
        run: echo "The result was ${{ steps.notify.outputs.slack-result }}"
      - name: Upload to slack step
        uses: adrey/slack-file-upload-action@master
        with:
          token: ${{ secrets.SLACK_BOT_USER_OAUTH_ACCESS_TOKEN }}
          path: ./app/build/outputs/apk/debug/app-debug.apk
          channel: test

完整的实例代码也可参考如下仓库

github.com/zhang632161…






参考资料

github.com/features/ac…

www.infoq.cn/article/D0m…

www.ruanyifeng.com/blog/2019/0…

www.mindtheproduct.com/what-the-he…

www.redhat.com/zh/topics/d…

help.github.com/cn/actions

www.ruanyifeng.com/blog/2015/0…