GitHub自动化Action工具


带你打开 GitHub 之门的全新方式

201911 月,GitHub 正式开放了 GitHub Actions 这个功能,现在不用申请就能使用。GitHub ActionsGitHub 官方推出的持续集成/部署模块服务(CI/CD),和 jenkinsTravis CI 是同一类产品定位,但是却有很多不同。

GitHub自动化Action工具


1. 工具介绍

官方推出的新一代 GitHub 命令行操作工具

自从微软收购了 Github 之后,相继推出了挺多的新功能和新特性,我自己使用一些,总的来说还是很不多的,大部分都很适用而且学习成本比较低、很容易上手和使用。

  • GitHub CLI
    • Take GitHub to the command line
    • 官方推出的新一代 GitHub 命令行操作工具
  • GitHub Actions
    • Automate from code to cloud
    • 一个轻量级的自动化 CI/CD 工具
  • GitHub Apps
    • More ways to work with GitHub
    • 一个多终端操作 GitHub 的手机软件
  • GitHub Packages
    • Your packages at home with their code
    • 一个包托管服务,允许开发者在上面托管包和代码,类似 npmdocker

GitHub自动化Action工具

我们使用 GitHub Actions 最大优势就是其与 GitHub 高度结合和整合,我们只需编辑一个配置文件,即可自动开启对应功能的服务,甚至不需要购买服务器。而且,GitHub Actions 也是可以复用的,即别人写的配置文件我们也可以拿来直接使用,达到相同的功能。

  • 持续集成 - Continuous Integration
    • 持续集成指的是频繁地将代码集成到主干
    • 好处在于快速发现错误和防止分支大幅偏离主干
    • 持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量
  • 持续交付 - Continuous Delivery
    • 持续交付是指频繁地将软件的新版本,交付给质量团队或者用户,以供评审
  • 持续部署 - Continuous Deployment
    • 持续部署是指的是代码通过评审以后,自动部署到生产环境
    • 持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段

GitHub自动化Action工具


2. 基本概念

GitHub Actions 有一些自己的术语,所以使用之前我们需要了解到 => 官方文档

  • [1] workflow - 工作流程

GitHub Actions 的配置文件叫做 workflow。我们编辑完成之后,需要存放到代码仓库的 .github/workflows 目录才可以起作用,同时一个库可以拥有多个 workflow 配置文件。workflow 配置文件采用 YAML 格式,文件名可以任意取,但是后缀名统一为 .yml

  • [2] job - 任务

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

  • [3] step - 步骤

每个 job 由多个 step 构成,一步步完成。

  • [4] action - 动作

每个 step 可以依次执行一个或多个命令 action


  • workflow 文件的配置字段非常多,下面是一些基本字段。
编号 配置文件字段 对应内容
1 name 设置 workflow 的名称;省略该字段默认为文件名称
2 on 触发 workflow 的条件;通常是触发某些事件生效
3 jobs.<job_id>.name 要执行的一项或多项任务;workflow 文件才是核心
4 jobs.<job_id>.needs 指定当前任务的依赖关系;即按照预先设置顺序运行
5 jobs.<job_id>.runs-on 指定运行所需要的虚拟机环境;目前包含多种虚拟机
6 jobs.<job_id>.steps 指定每个 Job 的运行步骤;可以包含一个或多个步骤
7 jobs.<job_id>.env 设置整个 Job 的所有步骤都可以使用的环境变量
8 jobs.<job_id>.steps.env 设置在 Job 的执行某个步骤才可以使用的环境变量
9 jobs.<job_id>.steps.run 在操作系统的 shell 中运行一条或者多条命令
10 jobs.<job_id>.steps.with 定义 step 在执行时需要输入的参数名称和对应值
# on
on: push
on: [push, pull_request]
on:
  push:
    branches:
      - master
# jobs.<job_id>.name
jobs:
  my_first_job:
    name: My first job
  my_second_job:
    name: My second job

# jobs.<job_id>.needs
jobs:
  job1:
  job2:
    needs: job1
  job3:
    needs: [job1, job2]

# jobs.<job_id>.runs-on
runs-on: ubuntu-18.04
runs-on: windows-2019
runs-on: macOS-latest

# jobs.<job_id>.steps
jobs.<job_id>.steps.name:步骤名称
jobs.<job_id>.steps.run:该步骤运行的命令或者action
jobs.<job_id>.steps.env:该步骤所需的环境变量

# jobs.<job_id>.steps.run
- name: Clean temp directory
  run: rm -rf *
  shell: bash
  working-directory: ./temp

# jobs.<job_id>.steps.run
- name: Clean install dependencies and build
  run: |
    npm ci
    npm run build
# jobs.<job_id>.steps.with
jobs:
  my_first_job:
    steps:
      - name: My first step
        uses: actions/hello_world@main
        with:
          first_name: Mona
          middle_name: The
          last_name: Octocat

# jobs.<job_id>.steps.with.entrypoint
steps:
  - name: Run a custom command
    uses: monacorp/action-name@main
    with:
      entrypoint: /a/different/executable
  • 下面是一个完整的 workflow 文件的范例。
# 打印设置的四个变量
name: Greeting from Mona

on: push

jobs:
  my-job:
    name: My Job
    runs-on: ubuntu-latest
    steps:
      - name: Print a greeting
        env:
          MY_VAR: Hi there! My name is
          FIRST_NAME: Mona
          MIDDLE_NAME: The
          LAST_NAME: Octocat
        run: |
          echo $MY_VAR $FIRST_NAME $MIDDLE_NAME $LAST_NAME.

  • workflow 文件的配置字段非常多,下面是容器构建相关的字段。
编号 配置文件字段 对应内容
1 jobs.<job_id>.container.image 设置 Job 需要运行的容器镜像名称
2 jobs.<job_id>.container.credentials 设置登录容器镜像仓库的用户名和密码
3 jobs.<job_id>.container.env 设置容器相关的环境变量
4 jobs.<job_id>.container.ports 设置要在容器上公开的端口数组
5 jobs.<job_id>.container.volumes 设置容器要使用的卷数组
# container
jobs:
  my_job:
    container:
      image: node:10.16-jessie
      env:
        NODE_ENV: development
      ports:
        - 80
      volumes:
        - my_docker_volume:/volume_mount
      options: --cpus 1
# credentials
container:
  image: ghcr.io/owner/image
  credentials:
    username: ${{ github.actor }}
    password: ${{ secrets.ghcr_token }}

# volumes
volumes:
  - my_docker_volume:/volume_mount
  - /data/my_data
  - /source/directory:/destination/directory

# services
services:
  myservice1:
    image: ghcr.io/owner/myservice1
    credentials:
      username: ${{ github.actor }}
      password: ${{ secrets.ghcr_token }}
  myservice2:
    image: dockerhub_org/myservice2
    credentials:
      username: ${{ secrets.DOCKER_USER }}
      password: ${{ secrets.DOCKER_PASSWORD }}

3. 简单使用

站在巨人的肩上,我们可以创造更多东西!

另外 GitHub 做了一个官方市场,可以搜索到他人提交的 actions。另外,还有一个 awesome actions 的仓库,也可以找到不少 action,比如发送邮件、发送天气、库编译等。每个 action 就是一个独立脚本,因此可以做成代码仓库,使用 userName/repoName 的语法引用 action。比如,actions/setup-node 就表示 github.com/actions/setup-node 这个仓库,它代表一个 action,作用是安装 Node.js。事实上,GitHub 官方的 actions 都放在 github.com/actions 里面。

  • [1] ansible-lint
    • This action allows you to run ansible-lint with no additional options.
# .github/workflows/ansible-lint.yml
# https://github.com/marketplace/actions/ansible-lint
name: Ansible Lint
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Lint Ansible Playbook
        uses: ansible/ansible-lint-action@master
        with:
          targets: ""
          override-deps: |
            ansible==2.9
            ansible-lint==4.2.0
          args: ""
  • [2] Create a Release
    • This GitHub Action wraps the GitHub Release API.
# .github/workflows/create-a-release.yml
# https://github.com/marketplace/actions/create-a-release
name: Create Release
on:
  push:
    tags:
      - "v*"

jobs:
  build:
    name: Create Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          body: |
            Changes in this Release
            - First Change
            - Second Change
          draft: false
          prerelease: false
  • [3] Setup Python
    • This action sets up a Python environment for use in actions
# .github/workflows/setup-python.yml
# https://github.com/marketplace/actions/setup-python
name: Setup Python
on: push

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["2.x", "3.x"]
    name: Python ${{ matrix.python-version }} sample
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
        with:
          python-version: "3.x"
          architecture: "x64"
      - run: python my_script.py
  • [4] Python Poetry Action
    • GitHub Actions for Python projects using poetry
# .github/workflows/python-poetry-action.yml
# https://github.com/marketplace/actions/python-poetry-action
name: Python Poetry Action
on: pull_request

jobs:
  ci:
    strategy:
      fail-fast: false
      matrix:
        python-version: [3.6, 3.7, 3.8]
        poetry-version: [1.0, 1.1.2]
        os: [ubuntu-18.04, macos-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
        with:
          python-version: ${{ matrix.python-version }}
      - name: Run image
        uses: abatilo/actions-[email protected]
        with:
          poetry-version: ${{ matrix.poetry-version }}
      - name: View poetry --help
        run: poetry --help

4. 示例演示

主要介绍几种简单的玩法!

  • [1] 自动部署 React 项目到 GitHub
# 将构建结果发送到GitHub仓库的话需要使用GitHub密钥
# https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line

# 1.程序运行在ubuntu-latest的虚拟机上
# 2.使用官方action的actions/checkout来获取源码
# 3.使用的JamesIves/github-pages-deploy-action来完成构建和部署

name: GitHub Actions Build and Deploy Demo
on:
  push:
    branches:
      - master

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@master

      - name: Build and Deploy
        uses: JamesIves/github-pages-deploy-action@master
        env:
          ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
          BRANCH: master
          FOLDER: build
          BUILD_SCRIPT: npm install && npm run build
  • [2] 使用 GitHub Actions 实现博客自动化部署
# 只在master上push触发部署
# 下列README.md和LICENSE文件的变更不触发部署

name: Deploy site files
on:
  push:
    branches:
      - master
    paths-ignore:
      - README.md
      - LICENSE

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Download
        uses: actions/checkout@v2

      - name: Deploy to Server
        uses: AEnterprise/rsync-[email protected]
        env:
          DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
          ARGS: -avz --delete --exclude='*.pyc'
          SERVER_PORT: "22"
          FOLDER: ./
          SERVER_IP: ${{ secrets.SSH_HOST }}
          USERNAME: ${{ secrets.SSH_USERNAME }}
          SERVER_DESTINATION: /home/escape/mysite/

      - name: Restart server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USERNAME }}
          key: ${{ secrets.DEPLOY_KEY }}
          script: |
            cd /home/fming/mysite/
            python manage.py migrate
            supervisorctl restart web
  • [3] 定时发送天气邮件
name: "GitHub Actions Weather Bot"

on:
  push:
  schedule:
    - cron: "0 21 * * *"

jobs:
  bot:
    runs-on: ubuntu-latest
    steps:
      - name: "Checkout codes"
        uses: actions/checkout@v1
      - name: "Get Weather"
        env:
          CITY=Beijing
          LANGUAGE="zh-CN"
          UNIT=m
          UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
        run:
          curl -H "Accept-Language: $LANGUAGE" -H "User-Agent: $UA" -o result.html wttr.in/$CITY?format=4\&$UNIT
      - name: "Get Date"
        run: echo "::set-env name=REPORT_DATE::$(TZ=':Asia/Beijing' date '+%Y-%m-%d %T')"
      - name: "Send mail"
        uses: dawidd6/action-send-mail@master
        with:
          server_address: smtp.163.com
          server_port: 465
          username: ${{ secrets.MAIL_USERNAME }}
          password: ${{ secrets.MAIL_PASSWORD }}
          subject: Beijing Weather Report (${{env.REPORT_DATE}})
          body: file://result.html
          to: [email protected]
          from: GitHub Actions
          content_type: text/html

5. 参考文章

送人玫瑰,手有余香!


文章作者: Escape
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Escape !
  目录