GitHub Actions 是 GitHub 的CI/CD服务,于2018年10月推出。
这里可能不是所有的小伙伴都理解CI/CD。我们稍微照顾一下不知道的小伙伴, 简单的介绍一下CI/CD。
它所要解决的问题
主要解决在集成新代码时所引发的一些问题
集成地狱是指交付团队中的成员集成其各自的代码时的生产点。在传统的软件开发环境中,这种集成过程很少是平滑且无缝的,而是需要花费数小时甚至数天的时间来修复代码,以便最终进行集成。持续集成(CI)旨在通过鼓励和鼓励团队成员进行频繁集成(例如每小时或至少每天一次)来完全避免这种情况
目标群体
它是针对开发,质量和运营团队的一种解决方案
它由三个核心概念组成
CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。这些关联的事务通常被统称为“CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。
到这里大家对CI/CD已经有个一个初步的认识
简单总结一下:
CI/CD 是一种通过在应用开发阶段引入自动化来频繁向客户交付应用的方法
CI/CD 既可能仅指持续集成和持续交付构成的关联环节,也可以指持续集成、持续交付和持续部署这三项构成的关联环节。更为复杂的是,有时“持续交付”也包含了持续部署流程。
归根结底,我们没必要死扣这些定义,只需记得 CI/CD 其实就是一个流程或者管道,用于实现应用开发中的高度持续自动化和持续监控。因案例而异,该术语的具体含义取决于 CI/CD 管道的自动化程度。许多企业最开始先添加 CI,然后逐步实现交付和部署的自动化(例如作为云原生应用的一部分)
概念: 一天多次或者频繁的将代码集成到主干
目的: 可以让产品快速迭代,还能保证质量
采用的方式: 在集成到主干之前必须要通过自动化测试和各种依赖安装正常
误解:持续集成并不能消除Bug,而是让它们非常容易发现和改正
持续集成偏重点在于开发人员提交了新代码之后,会立刻进行构建, 单元测试等操作。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。
概念: 频繁地将软件的新版本,交付给质量团队或者用户,以供评审
持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」production-like environments中。比如,我们完成单元测试后,可以把代码部署到连接数据库的 Staging 环境中更多的测试。如果代码没有问题,可以继续手动部署到生产环境中。
概念: 指的是代码通过评审以后,自动部署到生产环境
它是持续交付的下一步
最后用几张图来加深一下对各个概念的理解
持续集成
持续交付
持续部署
学会一个技能其实并不会让我们非常开心, 而是拿它做出点什么后,才会更加由成就感。
这是我的一个主观感受,不知道你们是不是也有同感。
现在让我们回到 GitHub Actions这里来,现在我们已经比较清楚的知道它什么样的一个服务,也知道了它能帮我解决什么样的问题。那么接下来,我需要自己搞一点事情,然后让它帮我们解决,以此来让我们学会如何使用GitHub Actions
当我们对GitHub Actions有了基本认识后。 那么我们该如何使用它来辅助我们呢?
要想让一个任务有始有终,就必须先要确定任务的边界,也就是确切的需求。
需求的产生又是源于我们对事物的思考。
目前针对Android端经过我的思考🤔,我提出了3点可以改进的地方:
目前暂定为 通知统一采用slack的指定channel,
依赖环境的确认, 命令打包, 和软件通信(Message, File)
针对上述需求,作为开发人员需要找到一个解决方案(给自己找一个光明正大使用GitHub Actions的理由)
Jenkins和Strider是开源软件,需要服务器资源支持
Travis和Codeship对于开源项目可以免费使用,不能用于私有项目
经过不断的搜索, GitHub Actions 进入了我的视野
它不要单独的部署服务器,由GitHub官方出品, 对于私有项目,提供了一定的限制支持
那么作为这么一个CI/CD界的新秀它有什么特点呢?
大家知道,持续集成由很多操作组成,比如切换分支,拉取代码、运行测试用例、登录远程服务器、发布到第三方服务等等。
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 文件采用 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系统还支持其他操作系统呢。 答案显然是肯定的
语法格式如下
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-artifact 和 download-artifact 操作.
在工作流程中作业之间传递数据
先创建一个SlackBot用于消息分发
第一步创建一个 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复制代码
完整的实例代码也可参考如下仓库
参考资料
www.ruanyifeng.com/blog/2019/0…
www.mindtheproduct.com/what-the-he…
www.ruanyifeng.com/blog/2015/0…