GitHub|一起编写个多用途 Github Action 吧!

GitHub|一起编写个多用途 Github Action 吧!


前言
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 类元数据:

  1. 描述类: name , author , description 这些字段来描述这个 action 是什么
  2. 入参: inputs 下的字段 , 用来给 action 传参
  3. 出参: outputs 下的字段 , 用于定义出参字段
  4. runs: 用于定义运行时相关的配置 , JavaScript action 和 Docker container action 有不同的配置 。 这篇文章主要介绍的是 JavaScript action
  5. 样式相关: branding 字段主要用于上架到 Github Marketplace 上的 icon 和颜色 。
这样我们就可以定义自己的元数据 action.yml:
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