Appearance
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);