Skip to content

官网

文档

Github Action基本概念

  • workflow: 一个 workflow 就是一个完整的工作流过程,每个workflow 包含一组 jobs任务。
  • job : jobs任务包含一个或多个job ,每个 job包含一系列的 steps 步骤。
  • step : 每个 step 步骤可以执行指令或者使用一个 action 动作。
  • action : 每个 action 动作就是一个通用的基本单元。

GitHubAction的使用

在项目库根路径下的.github/workflows目录中创建一个.yml 文件(或者 .yaml):

yaml
name: hello-github-actions
# 触发 workflow 的事件
on:
  push: # push为触发条件 可以是数组形式 ,查阅所有的触发事件 https://docs.github.com/cn/actions/using-workflows/events-that-trigger-workflows 
    # 分支
    branches:
      - master
# 一个workflow由执行的一项或多项job
jobs:
  # 一个job任务,任务名为build
  build:
    #运行在最新版ubuntu系统中
    runs-on: ubuntu-latest
    #步骤合集
    steps:
      #新建一个名为checkout_actions的步骤
      - name: checkout_actions
        #使用checkout@v2这个action获取源码
        uses: actions/checkout@v2 
      #使用建一个名为setup-node的步骤
      - name: setup-node
        #使用setup-node@v1这个action
        uses: actions/setup-node@v1
        #指定某个action 可能需要输入的参数
        with:
          node-version: '14'
      - name: npm install and build
        #执行执行某个shell命令或脚本
        run: |
          npm install
          npm run build
      - name: commit push
        #执行执行某个shell命令或脚本
        run: |
          git config --global user.email xxx@gmail.com
          git config --global user.name xxxx
          git add .
          git commit -m "update" -a
          git push
         # 环境变量
        env:
          email: xxx@gmail.com

手动触发事件

查阅所有的触发事件 https://docs.github.com/cn/actions/using-workflows/events-that-trigger-workflows

这里主要介绍手动触发和远程触发

手动触发

yaml
name: 小程序自动构建
'on':
  workflow_dispatch:  # 手动触发事件
    inputs:           # 输入
      appInfo:
        description: 小程序名称
        required: true
        default: 音乐派对_sing_weapp_1.0.0
        type: choice
        options:
          - 音乐派对_sing_weapp_1.0.0
          - 伴伴音乐派对_sing_qq_1.0.0
          - 恋恋CP_voice_weapp_1.0.0
          - 恋爱CP_voice_qq_1.0.0
          - 你画我猜组局_guess_weapp_1.8.3
          - 一起画一画_guess_qq_1.8.3
          - 皮队友_teammate_weapp_1.1.7
          - 皮队友_teammate_qq_1.1.7
          - Jump游戏团_teammate2_weapp_1.1.7
          - 对话闯关_dialog_weapp_1.0.10
          - 伴伴虚拟女友抖音_dialog_tt_1.0.10
          - 恋爱聊天小游戏_dialog2_qq_1.0.10
          - 你会聊天吗_dialog_qq_1.0.10
          - 喝酒神器_party_weapp_1.7.1
          - 聚会喝酒神器QQ_party_qq_1.7.1
          - 去玩测试合集_test_tt_1.0.10
      env:
        description: 环境
        required: true
        default: api
        type: choice
        options:
          - api
          - alpha
          - dev
jobs:
  build:
    name: build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth: '0'
      - name: Use Node.js 14.x
        uses: actions/setup-node@master
        with:
          node-version: 14.x
          cache: yarn
      - name: Get Build info by event
        id: build
        uses: ./ci/actions/build
        with:     # 可以通过 github.event.inputs 获取输入的值 变量的写法如下
          action: ${{github.event.action}}
          app-info: ${{ github.event.inputs.appInfo}}
          apiEnv: ${{ github.event.inputs.env}}
          # 。。。

如上就可以手动去仓库触发了

按需选择后执行 run

远程触发

远程触发也就是在我们电脑本地触发 github actions 不用去仓库手动点击

yaml
name: 小程序自动构建
'on':
  repository_dispatch:
    types:
      - webhook
# ...

就这

然后你本地调 github指定接口 https://docs.github.com/cn/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#repository_dispatch

推荐使用这个库,做了简单的封装 https://github.com/octokit/rest.js

js
require('dotenv').config()
const { Octokit } = require("@octokit/rest");
const inquirer = require('inquirer');
const buildList = require('../build.apps');
let buildChoice = buildList.map(v => {
  return `${v.name}_${v.appName}_${v.platform}_${v.version}`;
});

const octokit = new Octokit({
  auth: process.env.AUTH_TOKEN
});

const envChoice = ['api', 'alpha', 'dev'];

const workflows = ['是', '否']

let question = [
  {
    name: 'contain',
    type: 'list',
    message: '是否触发工作流?',
    choices: workflows
  },

]

let question2 = [{
  name: 'name',
  type: 'list',
  message: '请选择要打包的小程序',
  choices: buildChoice
},
{
  name: 'env',
  type: 'list',
  message: '请选择环境',
  choices: envChoice
}]

inquirer.prompt(question).then(answers => {
  if(!process.env.AUTH_TOKEN){
    console.error('你还未设置github token,请参考readme.md')
    return
  }
  if (answers.contain == '是') {
    inquirer.prompt(question2).then(answers2 => {
      let [cName, pkgName, platform, appVersion] = answers2.name.split('_')
      let apiEnv = answers2.env
      octokit.rest.repos.createDispatchEvent({
        owner: 'olaola-chat',
        repo: 'web-min-banban',
        event_type: 'webhook',
        client_payload: {
          cName, pkgName, platform, appVersion, apiEnv
        }
      }).then(result => {
        console.log('请访问: https://github.com/olaola-chat/web-min-banban/actions')
      }).catch(e=>{
        console.error(e)
      })
    })
  }
});

process.env.AUTH_TOKEN 需要在github 个人设置获取

通过dotenv加入环境变量

忽略.env避免提交

sh
yarn hook  #

自定义actions

文件结构

action.yml 固定的文件名,描述文件,描述输入的变量和输出的字段

yaml
name: 'Github Release Changelog Generator'
author: 'Artiely'
description: 'Returns the commit difference count between two git references.'
inputs:
  token:
    description: 'Your GITHUB_TOKEN'
    default: ${{ github.token }}
    required: false
  run-id:
    description: '小程序简要信息.'
    default: 'true'
    required: true

outputs:
  version:
    description: 'The version number of the tag created. example: 1.0.0'
  changelog:
    description: 'Markdown formatted changelog'
  compareurl:
    description: 'Comparing two branches to see what’s changed or to start a new pull request.'
  tag:
    description: 'Tag name.'
  appVersion:
    description: 'appVersion name.'
  cName:
    description: 'cName name.'
  platform:
    description: 'platform name.'
  pkgName:
    description: 'pkgName name.'
runs:
  using: 'node16'
  main: 'test.js'
branding:
  icon: 'list'
  color: 'blue'

js

js
import { getInput, setFailed, startGroup, info, endGroup, setOutput } from '@actions/core';
import { context, getOctokit } from '@actions/github';
import axios from 'axios'
import idName from '../idName.js'

async function run() {
  const { owner, repo } = context.repo;
  const myToken = getInput('token');
  const octokit = getOctokit(myToken);
  let listRun = await octokit.rest.actions.listJobsForWorkflowRun({
    owner,
    repo,
    run_id: context.runId,
  });

  info(`steps${JSON.stringify(listRun.data.jobs, null, 2)}`)

  var steps = listRun.data.jobs[0].steps.filter(v => {
    return v.name.indexOf('/github-tag-action') == -1
  }).map(v => {
    return `${v.conclusion == 'success' ? '✅ ' : v.conclusion == 'skipped'?'⚪ ':'❌ '}${v.name}`
  })

  // slack for
// 通知到slack
await axios.post(`https://hooks.slack.com/services/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`,{
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": ` *工作流结果*\n${steps.join("\n")} \n<https://github.com/${owner}/${repo}/actions/runs/${context.runId}/ | more>`
      }
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": `<@${idName[context.payload.sender.login]}>`
      }
    },
  ]
}).then((res) => {
  info("hook res", JSON.stringify(res, null, 2))
}).catch((e) => {
  info("hook err", JSON.stringify(e, null, 2))
})

}


try {
  run();
} catch (error) {
  if (error) {
    setFailed(error.message);
  }
}

引用自己写的

yaml
#...
jobs:
  notify:
    name: notify
    needs: build
    if: ${{ always() }}
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@master
        with:
          fetch-depth: '1'
      - name: Install
        run: cd ./ci && yarn && cd -
      - name: notify
        uses: ./ci/actions/fail
        with:
          token: ${{ secrets.GH_TOKEN }}

用json转yml

如下这么多options都是动态的不可能每次手动去维护yaml,而我们可以通过js写入json转yml

yaml
options:
          - 音乐派对_sing_weapp_1.0.0
          - 伴伴音乐派对_sing_qq_1.0.0
          - 恋恋CP_voice_weapp_1.0.0
          - 恋爱CP_voice_qq_1.0.0
          - 你画我猜组局_guess_weapp_1.8.3

利用 const yaml = require("js-yaml");

js
const path = require("path");
const fs = require("fs");
const buildList = require('../../build.apps');
const yaml = require("js-yaml");
let buildChoice = buildList.map(v => {
  return `${v.name}_${v.appName}_${v.platform}_${v.version}`;
});
const workflowJson = {
  "name": "小程序自动构建",
  "on": {
    workflow_dispatch: {
      inputs: {
        "appInfo": {
          "description": "小程序名称",
          "required": true,
          "default": buildChoice[0],
          type: "choice",
          options: buildChoice
        },
        "env": {
          "description": "环境",
          "required": true,
          "default": "api",
          type: "choice",
          options: ["api", "alpha", "dev"]
        },
      }
    },
    repository_dispatch: {
      types: ['webhook']
    }
  },
  jobs: {
    build: {
      name: 'build',
      'runs-on': "ubuntu-latest",
      steps: []
    }
  }
}
var res = yaml.dump(workflowJson, { lineWidth: -1 })
var filePath = path.join(__dirname, "../../.github/workflows/build.yml")
fs.writeFileSync(filePath, res);

结合slack通知效果