前言
Github Actions 想必大家或多或少都了解 , 并使用过类似的产品 。
这篇文章就从开发 , 测试 , 构建的角度来设计一个 Github Action , 让它可以便捷的复用代码逻辑 , 并同时发布到 Github Marketplace npm 等平台 。
快速开始
0. 从模板初始化项目
快速创建一个 ts rollup lib 项目 , 本人一般使用自己的模板() , 当然这无所谓 , 自己 npm init -y 也是可以的 。
1. 在根目录添加
这个文件是用来告诉 Github 这个仓库是一个 Action , Github 指南中给的示例如下:
name: 'Hello World' # 必填 Required GitHub Action 名称description: 'Greet someone and record the time' # 必填 Required 描述inputs: # 输入 who-to-greet: # id of input description: 'Who to greet' # 参数描述 required: true # 是否必填 default: 'World' # 此参数是一个字符串 , 文档中没有注明其他的类型outputs: # 输出 time: # id of output description: 'The time we greeted you'runs: using: 'node16' # 运行时 main: 'index.js' # 执行入口
从这个配置文件中 , 我们大体可以分为 5 类元数据:
- 描述类: name , author , description 这些字段来描述这个 action 是什么
- 入参: inputs 下的字段 , 用来给 action 传参
- 出参: outputs 下的字段 , 用于定义出参字段
- runs: 用于定义运行时相关的配置 , JavaScript action 和 Docker container action 有不同的配置 。 这篇文章主要介绍的是 JavaScript action
- 样式相关: branding 字段主要用于上架到 Github Marketplace 上的 icon 和颜色 。
name: 'github-repository-distributor'description: 'github-repository-distributor'inputs: token: # id of input description: 'the repo PAT or GITHUB_TOKEN' required: true username: description: 'github username to generate markdown files' required: true motto: description: 'whether add powered by footer (boolean)' default: 'true' # 注意这里是字符串 # .... title: description: 'main markdown h1 title' onlyPrivate: description: 'only include private repos (boolean)' default: 'false'runs: using: 'node16' main: 'lib/index.js'branding: icon: 'arrow-up-circle' color: 'green'
2. 创建入口
async function main(){ // do somethingmain()
3. 获取参数以及
这里就需要介绍 @actions/core 和 @actions/github
@actions/core 里面包含了大量 action 的核心方法 , 我们获取参数 , 导出变量 , 或者获取秘钥等等都得靠它 。
@actions/github 则主要包含了 Github 的上下文和一个 @octokit/core , 它能够直接帮助我们调用 Github 的 rest api 接口们 。
这样我们获取 inputs 里的参数就可以这么写:
import core from '@actions/core'import type { UserDefinedOptions from './type'export function getActionOptions (): UserDefinedOptions { const token = core.getInput('token') const username = core.getInput('username') // getBooleanInput 其实本质上就是一种 parseBoolean(core.getInput('key')) const motto = core.getBooleanInput('motto') const filepath = core.getInput('filepath') const title = core.getInput('title') const includeFork = core.getBooleanInput('includeFork') const includeArchived = core.getBooleanInput('includeArchived') const onlyPrivate = core.getBooleanInput('onlyPrivate') return { token username motto filepath title includeFork includeArchived onlyPrivate
- 华为荣耀|如果当时余承东跟着荣耀一起离开了华为,离开后会产生什么后果
- 家庭影院|G5800搭建家庭影院效果到底怎么样?和资深发烧友一起现场体验,真香!
- 有赞|有赞CEO白鸦内部信:奔向人均50万年度目标,一起实现正向现金流
- 红米手机|与Redmi K50相比,前代K40优缺点有哪些?一起聊一聊
- 华夏小康|世界水日,与碧然德一起享受“减悦生活”
- 三星|5款旗舰手机屏幕对比,放在一起竟难分难解,你更喜欢谁的观感?
- |到底能砍完吗?六万人一起帮忙砍拼多多,结果砍到了小数点后六位
- GitHub|备胎计划全面发威!俄被踢出SWIFT后毫不担心:3周大赚150亿美元
- 华为|二手手机值得买吗?怎么买?一起来看看华为一代神机钉子户mate20系列
- 李宁|说到门店管理,一起来看看中国李宁