本文目标
阅读本文你将有如下收获
GitHub Actions 是什么?
GitHub Actions 如何使用?
案例讲述使用 GitHub Actions 打包构件, rsync 免密登陆, 同步代码到 cvm,SSH 远程命令行修改发布回滚
GitHub Actions 是什么?
官方解释: Automate your workflow from idea to production
简言之: 它是 GitHub 推出的持续集成部署的工具, 目前优秀的 cicd 工具包括: travis ci,jenkins
你可以这么理解: 经过一个动作 (自动触发, 手动触发, 定时触发) 唤醒它, 剩下操作 (actions) 它来做
(例如: 打包, 构建, 集成, 测试, 预发布, 打镜像, 上生产..., 只有你想不到的, 没有它做不到的)
CICD 工具
GitHub Actions 如何工作的?
为了把概念讲的通俗易懂, 我们来看个点餐流程
如下图:
点餐流程
GitHub actions 的概念名词
如下图:
order.YAML
名次解释
workflow (工作流水线): 多个任务组成的工作流,
一个项目下可以有多条工作流
水线.
on (触发时机): 可以定时触发, 可以监听 push,pr 触发, 可以
监听分支, 文件夹, tags 等, 非常之多
.
jobs (阶段任务): 一个流水线由多个任务组成, 每个任务有
单独的运行环境
, 任务可以并行, 可以串行.
(操作步骤): 阶段任务由多个操作步骤组成, 操作步骤串行.
actions (操作动作): 每个步骤所需要的工具, 可以理解为每一步骤内的小操作点. 官方提供了插件市场 https://github.com/marketplace?type=actions , 还可以自己编写, 目前支持 JS 和 docker 两种创建方式.
两外还需要了解两个重要的参数
runs-on(任务的环境): 目前官网提供三种环境, 支持 self-host
env (环境变量): 支持 GitHub 私有变量, workflow 全局变量, job,step 局部变量
项目及文档结构
使用前提: 需要创建 GitHub 仓库(公有, 私有仓库都可以使用)
根据上图我们模拟一份 YAML 来介绍名词
项目文件夹结构
- order_proj/ // ---> 仓库名
- --.GitHub/ // ---> .GitHub 文件夹 必须
- ----workflows/ // ---> workflows 文件夹 必须
- ------order.YAML // ---> 工作流程文件 必须
- --src/ // ---> 源代码
order.YAML 文件内容结构
name: GitHub Actions order.YAML
- on:
- push:
- branches:
- - master
- pull_request:
- branches:
- - master
- jobs:
- // 煮饭任务
- job1_zhufan:
- // 在哪里执行任务
- runs-on: Ubuntu-latest
- steps:
- // 把米装进盒子, 拉取代码
- - name: box
- uses: actions/box@master
- // 清洗
- - name: wash
- uses: actions/wash@master
- // 开始煮饭
- - name: steam
- uses: actions/steam@master
- env:
- // 设定的煮饭的时间
- set_time: 10000
- // 并行煮菜
- job2_zhucai:
- ...
- // 前两步完成打包
- job3_dabao:
- needs: [job1, job2]
- ...
- // 打包完成配送
- job4_paisong:
- needs: job3
- ...
举例说明
经过上面的说明, 相信你应该对 GitHub actions 是什么应该有个大致的了解了, 接下来我们用一个例子实践一下
案例说明: 主要内容是动态构建前端代码, 将构件压缩包发布到远程机器, 创建软连, 修改生产文件夹软连指向的模拟
环境依赖: GitHub 仓库, 任意配置的一台 cvm 机器
案例所需要了解的知识: SSH 免密登陆
所用到的 action 插件
actions/checkout@v2 : 拉代码
actions/cache@v1: 缓存
actions/upload-artifact@v1: 打包上传构件
actions/download-artifact@v1: 下载构件
easingthemes/SSH-deploy@v2.0.7:SSH-deploy 部署插件
contention/rsync-deployments@v1.0.0:rsync 同步插件
appleboy/SSH-action@master:SSH 命令行插件
先把 rsync 搞明白
搞明白谁免密登陆谁, 私钥存在哪里, 公私钥怎么生成
前文已经讲过, 每个 job 会有独立的运行环境(runs-on), 使用 rsync 或者 SSH-action 两个工具的时候才会用到免密登陆
先看张图, 理解一下机器环境配置
关系图
仓库中对应的密钥设置
SSH 公私钥生成
记住在生成机器上为 GitHub actions 构建机创建单独的用户
- # 在 rs2 创建专属账户, 生成公私钥
- # 注意: gid 和 uid 均为 1212, 此为示例, 也可以选用其它值, 只要保证不和现有的用户和组冲突
- cat /etc/group
- # "-m" 表示要为 GitHub 用户创建 home 目录, 即 / home/GitHub/
- # 创建用户组 GitHub
- $ groupadd -g 1212 GitHub
- # 创建 GitHub 用户, 并加入 GitHub 用户组
- $ useradd -m -s /bin/bash -g 1212 -u 1212 GitHub
- # 为 GitHub 创建. SSH 目录
- $ mkdir /home/GitHub/.SSH
- $ chown GitHub:GitHub /home/GitHub/.SSH
- # 要上传的文件夹 $ chown GitHub:GitHub /home/rsynctest
- # 注意上面文件夹的权限, 要限制用户权限在此文件加下操作
- # 在哪一台机器上创建公私钥都可以, 但是要登陆或者目标主机要存放公钥, 存放在当前用户的. SSH/
- # [rs2] 用 SSH-keygen 生成密钥
- [root@xxxx ~]$ SSH-keygen
- Generating public/private rsa key pair.
- Enter file in which to save the key (/root/.SSH/id_rsa): //rsync_id_dsa
- Enter passphrase (empty for no passphrase): // 输入空
- Enter same passphrase again: // 输入空
- Your identification has been saved in /home/GitHub/rsync_id_dsa.
- Your public key has been saved in /home/GitHub/rsync_id_dsa.pub.
- # 将公钥存放在. SSH 目录下
- cp /home/GitHub/rsync_id_dsa.pub /home/GitHub/.SSH
- # 公钥导入 / home/GitHub/.SSH / 的 authorized_keys 文件
- $ cd /home/GitHub/.SSH
- $ cat rsync_id_dsa.pub> authorized_keys
- $ chown GitHub:GitHub authorized_keys
- # 将私钥内容存储到 GitHub-->仓库 -->setting--->secret
编写 workflow 文件
- name: deploy
- on:
- push: # 当发生推送事件时
- tags: # 当推送 tag 时
- - v*
- branches: # 当推送分支时
- - master
- #paths: [ src/* ]
- pull_request: # 当发生合并事件时
- branches:
- - master
- # 流水线变量查看: https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables
- env:
- WORKFLOW_ID: ${{GitHub.run_id}}
- WORKFLOW_NUMBER: ${{GitHub.run_number}}
- WORKFLOW_WORKSPACE: ${{GitHub.workspace}}
- WORKFLOW_COMMITID: ${{GitHub.sha}}
- BUILD_SCRIPT: "npm run newprod"
- ARGS: "-rltgoDzvO --delete"
- TARGET: "/home/rsynctest/vwork${{github.run_number}}" # 这个一定是 rsync 用户的有权权限的目录
- WWWROOT_DIR: "/home/rsynctest"
- REMOTE_HOST: ${{ secrets._HOST }}
- REMOTE_PORT: ${{ secrets._PORT }}
- REMOTE_USER: ${{ secrets._USERNAME }}
- SSH_PRIVATE_KEY: ${{ secrets._SECRET }}
- jobs:
- build: # 构建安装依赖, 构建文件
- name: "Build"
- runs-on: Ubuntu-latest
- steps:
- - uses: actions/checkout@v2 # 拉去分支
- - name: Cache node modules #缓存依赖
- uses: actions/cache@v1
- env:
- cache-name: cache-node-modules
- with:
- path: ~/.NPM # NPM cache files are stored in `~/.npm` on Linux/macOS
- key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
- restore-keys: |
- ${{ runner.os }}-build-${{ env.cache-name }}-
- ${{ runner.os }}-build-
- ${{ runner.os }}-
- # - name: Install Dependencies
- # run: NPM i
- #
- # - name: NPM run build
- # run: $BUILD_SCRIPT
- - run: mkdir dist && echo 3333> dist/index.html
- - run: mkdir zip
- - run: cd dist && zip -rq dist.zip ./* && mv dist.zip ../zip
- - name: Upload Artifact
- uses: actions/upload-artifact@v1
- with:
- name: dist
- path: zip
- deploy:
- name: Deploy
- needs: build
- runs-on: Ubuntu-latest
- steps:
- - name: Download result
- uses: actions/download-artifact@v1
- with:
- name: dist
- - run: ls -la
- # use SSH-deploy
- # - uses: easingthemes/SSH-deploy@v2.0.7
- # env:
- # SSH_PRIVATE_KEY: ${{ secrets._SECRET }}
- # ARGS: "-rltgoDzvO --delete"
- # #SOURCE: dist/
- # SOURCE: ./dist.zip
- # REMOTE_HOST: ${{ secrets._HOST }}
- # REMOTE_USER: ${{ secrets._USERNAME }}
- # TARGET: ${{env.TARGET}}
- # use rsync-deployments
- - name: rsync deployments
- uses: contention/rsync-deployments@v1.0.0
- env:
- DEPLOY_KEY: ${{env.SSH_PRIVATE_KEY}}
- UPLOAD_DIR: ${{env.TARGET}}
- with:
- args: "-avzr --delete ${{env.REMOTE_USER}}@${{env.REMOTE_HOST}}:${{env.UPLOAD_DIR}}"
- # use SSH-commands
- - name: Switch SoftLink
- uses: appleboy/SSH-action@master
- env:
- softlinkname: "test.vwork"
- with:
- host: ${{ env.REMOTE_HOST }}
- username: ${{ env.REMOTE_USER }}
- key: ${{ env.SSH_PRIVATE_KEY }}
- port: ${{ env.REMOTE_PORT }}
- script_stop: true
- script: |
- cd ${{env.TARGET}}
- unzip -o dist/dist.zip -d .
- rm -rf dist
- ls -la
- cd ${{env.WWWROOT_DIR}}
- if [ ! -L "${{env.softlinkname}}" ]; then
- if [ -d "${{env.softlinkname}}" ]; then
- rm -rf ${{env.softlinkname}}
- fi
- ln -snf "vwork${{github.run_number}}" "${{env.softlinkname}}"
- fi
- pre_link=`readlink -f ${{env.softlinkname}}`
- echo "$pre_link"> "${{env.WWWROOT_DIR}}/pre_link_${{env.softlinkname}}"
- # 清理文件
- # 切换软连
- ln -snf "vwork${{github.run_number}}" "${{env.softlinkname}}"
- ls -la
- exit 0
最后的效果图
最后, 你可以提交代码触发测试一下
- travis-ci: https://travis-ci.org/
- jenkins: https://jenkins.io/zh/
来源: https://www.qcloud.com/developer/article/1614404