用 JavaScript 创建 GitHub Action

2023.03.31

初始化

首先创建一个仓库

shell
git init

然后,初始化项目

shell
npm init

接着安装相关依赖 @actions/core@actions/github
其他的工具包在这里 toolkit
但是想用 GitHub API 的话就不用安装 octokit 了,因为 @actions/github 已经封装好了这个包。

shell
npm install -D @actions/core @actions/github

配置文件

新建 action.yml

yaml
name: 'say hello'
description: 'test for GitHub Actions!'
# 需要输入的字段
inputs:
  # 输入字段名称
  name:
    # 字段描述
    description: 'name'
    # 默认值 
    default: 'ttdly'
    # 是否必须
    required: true
# 需要输出的字段
outputs: 
  hello: 
    description: 'say hello'

runs:
  using: 'node16'
  main: 'index.js'

关于 action.yml 的语法,可以参考 官方文档,但是上面俩字段基本够用了。

编写 & 本地测试

新建 js 入口文件 index.js,可以是任何名称,但是 runs.mian.<name> 字段一定要和入口文件名字一致

输入输出

javascript
const core = require ('@actions/core');
const github = require ('@actions/github');

const core = require ('@actions/core')

async function run (){
  try {
    const name = core.getInput ('name')
    core.setOutput ('hello', `Hello ${name}`)
  } catch (err) {
    core.setFailed (err.message)
  }
}

run ()

可以看的出来,平时 Javascript 怎么写,这里就能怎么写,只是输入输出方式不一样,这里列举一下输出的类型:

  • core.info ()
  • core.debug ()
  • core.warning ()
  • core.notice ()
  • core.error ()

结合 GitHub API

虽然在执行工作流的时候,github context 提供了许多信息,但是也并不包含有关事件的所有信息,这时就要用到 GitHub API 来获取一些额外的数据。
通过以下步骤获取到可以直接执行 graphql 查询的工具:

javascript
const github = require ('@actions/github')
const octokit = github.getOctokit (token)
const graphqlWithAuth = octokit.graphql

然后编写查询语句,这里简单一些,获取当前登录用户的名称:

graphql
query {
  viewer {
    login 
  }
}

较为复杂的语句建议在 官方工具 中编写。 执行查询语句,获取数据:

javascript
const data = await graphqlWithAuth (`
query {
  viewer {
    login 
  }
}
`)
console.log ('login:',data.data.viewer.login)

注意,在执行 graphql 查询时,如果需要在查询语句中传递参数,官方建议是这么写的。(代码摘自 octokit/graphql.js

javascript
const { graphql } = require ("@octokit/graphql");
const { lastIssues } = await graphql ({
  query: `query lastIssues ($owner: String!, $repo: String!, $num: Int = 3) {
    repository (owner:$owner, name:$repo) {
      issues (last:$num) {
        edges {
          node {
            title
          }
        }
      }
    }
  }`,
  owner: "octokit",
  repo: "graphql.js",
  headers: {
    authorization: `token secret123`,
  },
});

也就是你需要传递的参数也得放在请求里面,而不是用模板字符拼接,因为用模板字符拼接可能会遭受注入攻击。而且也更方便进行一些递归查询。

本地测试

目前我知道的,比较专业的 action 测试是 act,不过也没了解过,我是通过修改环境变量的方式来进行本地测试的。

input

对于利用 Javascript 来创建的 GitHub Actions,action.yml 中的 input 字段,会在运行时转换成 INPUT_XXX 并且空格会转换成 _。例如你的 input 字段是 time,那存储在环境变量里面的就会是 INPUT_TIME 字段,可以设置 process.env ['INPUT_TIME']=10 来模拟输入。

context

context 中的字段在 process.env 中的字段,基本就是 GITHUB_XXX(该字段的 upperCase),驼峰命名使用 _ 连接,如 eventName 就是 process.env.GITHUB_EVENT_NAME
但是 payload 比较特殊,需要给 process.env.GITHUB_EVENT_PATH 设置一个 json 文件的文件路径,内容就是 Action 执行的上下文,也就是 github context 中的内容。

基本上这些数据就能够进行一些简单的流程测试。

本文最后更新于 2023 年 4 月 9 日