神代綺凛の随波逐流

GitHub Actions 踩坑之——自己造!


当前页面是本站的「Baidu MIP」版。查看和发表评论请点击:完整版 »

最近闲着研究了下怎么做一个 Action,并且研究了下组合式 Action,挺好玩,但是坑还挺多的

Head Pic: #明日方舟 夏天!泳装!和整点薯条 - 八伝的插画 - pixiv

提丰真大 ::aru:shy2::

背景

最近研究完明日方舟的整个解包流程,于是把我方舟工具箱里数据自动更新的流程都换成了自己解包的流程,其中涉及到检查更新、下载数据等步骤

这些步骤都有单独的代码放在单独的仓库里,写在 Workflow 里非常繁琐,我需要检出、安装依赖、执行,至少三个步骤,而且 github 官方的 checkout action 只能检出到工作区内,对工作区有一定污染,于是我想能不能整成 action,直接一个步骤就解决了不是爽多了

制作 Action

本文默认读者有一定的 GitHub Actions 基础,包括有 GitHub Actions 的使用经验,并多少了解 GitHub Workflow 的配置语法

1. 适配 Action

做成 Action 的一大好处就是可以直接从 Action 接收参数,而不用自己去处理命令行参数或环境变量等,引入 GitHub 官方的 @actions/core 即可,这里有一切你想要的功能

另外我们还需要编写 action.yml,用于声明这个 Action 的输入和输出等,具体可以直接看官方文档 GitHub Actions 的元数据语法

2. 编译

我这都是 js 或 ts 的项目,编译方面首推 vercel/ncc,这是一个零配置编译工具,并且 cjs mjs ts 都可用,很方便,一行命令即可生成产物

3. 发布

一个 Action 并不需要发布到 GitHub Marketplace 中才能被使用,你可以将它发布到一个单独的分支,甚至在分支的某个文件夹中

我个人比较推荐直接发布到单独的分支中

如果你在编写对外的 Action,需要版本管理,那么我推荐使用 JasonEtco/build-and-tag-action

由于我这个场景不需要,所以直接简单粗暴使用 casperdcl/push-dir 即可

以下是用于发布的 Workflow 示例

name: Publish

on:
  workflow_dispatch:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v3
      - name: Install dependencies
        run: yarn install --frozen-lockfile
      - name: Build
        run: yarn build
      - name: Push dist
        uses: casperdcl/push-dir@v1
        with:
          message: ${{ github.sha }}
          branch: dist
          dir: build
          history: false

其中 npm 的 build 脚本为

ncc build src/index.mjs -o build/dist --target es2022

编译完成后目录结构

build
├── action.yml
└── dist
    └── index.mjs

action.yml 中指定的入口文件为 dist/index.mjs

该 Workflow 会将 build 文件夹内的内容推送到 dist 分支,后续我们就可以在其他项目的 Workflow 中使用该 Action 了

4. 使用自制 Action

steps:
  # 使用某个分支
  - uses: user/repo@branch
  # 使用某个分支的某个文件夹
  - uses: user/repo/folder@branch

分支是必须的,即使适用的是默认分支也必须加上 @branch

如果你的 Action 在私有仓库中,那么需要注意:私有 Action 只能被同一用户/组织私有仓库使用

也就是说,私有 Action 是不能直接在公有仓库中使用的,不同用户/组织间的私有 Action 也不能在私有仓库中使用,可能是为了安全规定的,但我觉得挺蠢就是了……(但给钱买企业版的话可以在组织内转为内部仓库来解决这个问题,但是要给钱)

不过有方法绕过,后面讲

并且私有 Action 需要经过设置才能被使用,具体进入仓库 Settings - Actions - General - Access,选择第二项

如果你一定要在公有仓库中使用私有 Action,或者跨用户/组织在私有仓库中使用私有 Action,那么有个办法就是先 clone 过来再本地运行

没错,GitHub Workflow 支持执行本地的 Action,但你需要准备一个 access token 用来检出其他仓库,Workflow 自带的 token 只有本仓库的读写权限

steps:
  - uses: actions/checkout@v3
    with:
      repository: user/repo
      ref: branch
      path: ./some/path
      token: ${{ secrets.YOUR_GITHUB_TOKEN }}
  - uses: ./some/path

这里有一点需要注意,执行本地 Action 必须在工作区内,也就是说你没办法自行使用 git clone 某个 repo 到工作区外的某个文件夹然后 uses 一个绝对路径或 .. 开头的相对路径

组合操作 (Composite Action)

组合操作,顾名思义,可以将多个步骤组合成一个可复用的 Action,可以在一定程度上简化 Workflow

1. 创建组合操作

也是创建一个 action.yml 文件,元数据方面跟普通 Action 区别不大,只有 runs 配置有区别

组合操作的 runs.using 必须为 composite,并且需要提供 runs.steps 配置,跟 Workflow 的 steps 是基本一样的,具体可看官方文档 创建组合操作

特别地,组合操作可以通过 github.action_path 上下文获得操作的根目录

2. 使用组合操作

你可以将组合操作的 action.yml 放在一个仓库里 clone 下来本地执行,也可以跟一般操作一样直接以 uses: user/repo@branch 的形式使用

一些注意点

  1. uses 必须是确定的,不可是动态的
  2. uses 本地操作不能位于工作区之外