如何写一个其他人可以使用的GitHub Action
前言
在
GitHub
中,你肯定会使用GitHub Actions
自动部署一个项目到GitHub Page
上,在这个过程中总要使用workflows
工作流,并在其中使用action
,在这个使用的过程中,总会好奇怎么去写一个action
呢,所以,我对此进行了一个学习。
什么是GitHub Actions
- 官方概述如下:
GitHub Actions 是一种持续集成和持续交付 (CI/CD) 平台,可用于自动执行生成、测试和部署管道。 您可以创建工作流程来构建和测试存储库的每个拉取请求,或将合并的拉取请求部署到生产环境。
GitHub Actions 不仅仅是 DevOps,还允许您在存储库中发生其他事件时运行工作流程。 例如,您可以运行工作流程,以便在有人在您的存储库中创建新问题时自动添加相应的标签。
GitHub 提供 Linux、Windows 和 macOS 虚拟机来运行工作流程,或者您可以在自己的数据中心或云基础架构中托管自己的自托管运行器。
-
上述关键词:
CI/CD
,持续集成由很多操作组成,比如拉取代码、限定npm
版本、下载依赖、运行测试、docker
部署,发布到第三方服务等等。GitHub
把这些操作就称为actions
。 -
其实很多操作在不同项目里面都是类似的,完全可以使用相同的代码逻辑。
GitHub
允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用。 -
如果说你需要某个
action
,不必自己写复杂的脚本,直接引用他人写好的action
就行,整个持续集成过程,就变成了一个actions
的组合。这就是GitHub Actions
最特别的地方。 -
GitHub
做了一个官方市场,可以搜索到他人提交的actions
。
如何写一个GitHub Action
经常使用其他人写好的
action
,或者说觉得其他人写的action
并不好用,难免有时候会想自己写一个
- 在上文中提到,
GitHub
允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用。
初始化一个项目仓库
-
在
GitHub
新建一个代码仓库 -
本地初始化项目,并与远程仓库相连接
npm init -y
action.yml
文件
- 在项目的根目录下,新建
action.yml
文件 - 以下是我写的
action
的部分action.yml
文件代码,也包含注释
name: 'action-demo' # action的名字
description: 'GitHub Action data-cards' # 描述
author: 'lxKylin' # 作者
# 定义输入参数
inputs:
github_token: # 参数
description: 'Your GitHub token for authentication.' # 描述
required: true # 是否必须
# 定义输出参数
outputs:
result:
description: 'action-demo'
runs: # 脚本运行环境
using: node16
main: 'dist/index.js' # 执行入口
安装必要的依赖
@actions/core
npm install @actions/core
@actions/core
用于创建和管理GitHub Actions
的工作流程。它提供了一些基本的功能,帮助你在工作流程中定义输入参数、设置环境变量、输出结果等。- 提到定义输入参数,在上文的
action.yml
文件中,我们定义了一个叫github_token
的输入参数,我们可以根据@actions/core
包中的getInput()
方法获取到:
const core = require('@actions/core')
const token = core.getInput('github_token')
@actions/github
npm install @actions/github
@actions/github
包允许你在 GitHub Actions 工作流中访问触发动作的事件负载、上下文和仓库信息。通过这个包,你可以轻松地获取有关触发动作的信息,例如推送到仓库的提交信息、触发工作流的事件类型等。
const github = require('@actions/github')
// 上下文信息
const context = github.context
// 仓库所有者
const owner = context.repo.owner
// 仓库名
const repo = context.repo.repo
- 通过
owner
和repo
,我可以用之对相应的仓库进行提交等操作
@vercel/ncc
@vercel/ncc
可以将一个Node.js
模块及其依赖项打包到一个单一的JavaScript
文件中,这有助于提高应用程序的性能和加载速度。这个工具的主要目的是减少模块的加载时间,使应用能够更快地启动和执行。
npm install @vercel/ncc
- 这将以
main.js
为入口文件,在指定的目录dist
中生成一个单一的文件(index.js
),其中包含了你的 Node.js 模块及其依赖项。
ncc build main.js -o dist
package.json
"scripts": {
"build": "ncc build main.js -o dist"
},
- 完成以上几步,写一个
action
项目的架子就已经搭好了,其余就是写你的action
需要的逻辑了 - 你需要注意的是,在你具体的
action
逻辑代码有所修改后,一定要执行npm run build
进行重新打包生成dist
文件夹,这样代码提交后,使用这个action
时才是你最新的代码。 - 如果你觉得每次修改完代码都得重新
npm run build
有点烦,那么你完全可以在action
项目中写一个ci
,当你的代码提交时,自动打包,并将更新的代码提交到该分支
自动打包并提交
- 在上文中提到,可以写一个
ci
自动打包并提交代码,完整的代码如下:
name: Upload Action File
on:
push:
branches:
- action
workflow_dispatch:
jobs:
Upload_Action_File:
runs-on: ubuntu-latest # 运行环境
steps:
- name: Checkout code # 获取仓库代码
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v3 #安装node.js
with:
node-version: '16'
- name: install & build
run: |
echo "npm run build"
npm install
npm run build
- name: Upload Action File
uses: actions/upload-artifact@v4
with:
name: index.js
path: dist
- name: Download Action File
uses: actions/download-artifact@v4
with:
name: index.js
path: dist # 指定下载到本地的路径
- name: Delete Image Folder
run: |
echo "开始删除dist/image文件夹"
rm -rf dist/image
echo "成功删除dist/image文件夹"
shell: bash
- name: Commit and Push Changes
run: |
echo "Commit and Push Changes"
git config --global user.name "${GITHUB_ACTOR}"
# git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com"
git config --global user.email "actions@github.com"
git add .
git commit -m "feat: Update Action File"
# origin 是远程仓库的默认名称,而 HEAD:main 表示将本地的 HEAD 分支(通常是当前分支)推送到远程仓库的 action 分支
git push origin HEAD:action
env:
GH_TOKEN: ${{ secrets.DATA_CARD_TOKEN }}
name
是这个workflows
工作流的名称on
表示触发这个workflows
的条件,在上述代码中,当action
分支有push
操作时,便执行这个工作流- 也有数组写法:
[push, pull_request]
,表示push
、pull_request
都将触发这个工作流 workflow_dispatch
表示这个工作流可以手动触发:
- 也有数组写法:
jobs
表示的是任务,其下的Upload_Action_File
是任务的名称,是可以自定义的,每一个任务都是异步执行执行的,如果说,你需要每一步都按照顺序来,你可以这样使用needs
:
jobs:
job1:
job2:
needs: job1
job3:
needs: [job1, job2]
-
runs-on
表示运行环境,一般就是ubuntu-latest
-
steps
表示任务的步骤name
就表示这个步骤的名字,如果说,你是直接使用他人写好的action
,那么可以使用uses
进行引用with
,这里表示的是作业级别使用with
来定义步骤的配置。像这里with: node-version: '16'
就是你使用with
指定node
的版本,它还可以指定步骤的运行环境、虚拟机的操作系统、以及其他特定于作业的参数
-
actions/upload-artifact@v4
和actions/download-artifact@v4
是步骤间共享数据所使用到的action
,前者表示将生成的文件上传,后者表示将文件下载- 在这里,在执行
npm run build
时,会生成dist
文件夹,我们需要拿到这个文件夹中的文件,所以需要用到步骤间的数据共享
- 在这里,在执行
-
在
Commit and Push Changes
这一步骤呢就是平常我们配置git
的操作,设置用户名称和邮箱"${GITHUB_ACTOR}"
这个可以获取到你的账户名"${GITHUB_ACTOR}@users.noreply.github.com"
这个可以获取到你在github
设置的邮箱。而"actions@github.com"
相当于使用action
用户进行提交,最后的就是我们平时提交代码时的步骤啦
-
最后这个
env: GH_TOKEN: ${{ secrets.DATA_CARD_TOKEN }}
,需要到下图所示的地方进行生成一个具有你仓库读写权限的token
- 在上面生成
token
后,再到下图所示的地方进行配置
- 最后最后,为了确保这个
workflows
可以正常执行,在下图所示,你也需要给足workflows
读写的权限
例子:data-card
-
这个
action
是在学习写一个action
项目时写的一个用于生成网页数据的卡片,比如:掘金、CSDN、力扣、语雀等,当然,这种数据卡片,最好还是使用img
标签使用api
直接请求后端返回图片。这个仅作为一个学习的例子。 -
使用方法:
name: generate-data-card
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
jobs:
generate-card:
runs-on: ubuntu-latest
steps:
- name: Use Data Card Action
uses: lxKylin/data-card@action
with:
github_token: ${{ secrets.DATA_CARD_TOKEN }}
juejin_id: ${{ secrets.JUEJIN_PARAMS }} # 也可不使用变量,直接写juejin_id
- 该项目不断完善中