简介
在本指南中,您将了解创建和使用打包的 JavaScript 操作所需的基本组件。为了将本指南的重点放在打包操作所需的组件上,操作代码的功能是最小的。该操作在日志中打印“Hello World”,或者如果您提供自定义名称,则打印“Hello [who-to-greet]”。
本指南使用 GitHub Actions 工具包 Node.js 模块来加快开发速度。有关详细信息,请参阅actions/toolkit存储库。
完成本项目后,你应该了解如何构建你自己的 JavaScript action 并在工作流程中对其进行测试。
为了确保你的 JavaScript actions 与所有 GitHub 托管的 runner(Ubuntu、Windows 和 macOS)兼容,你编写的打包 JavaScript 代码应为纯 JavaScript 代码,并且不依赖于其他二进制文件。JavaScript actions 直接在 runner 上运行,并使用 runner 镜像中已存在的二进制文件。
警告
创建工作流程和 actions 时,应始终考虑你的代码是否可能执行来自潜在攻击者的不受信任的输入。某些上下文应被视为不受信任的输入,因为攻击者可能会插入他们自己的恶意内容。更多信息,请参阅“GitHub Actions 的安全加固”。
先决条件
在开始之前,你需要下载 Node.js 并创建一个公共 GitHub 仓库。
-
下载并安装 Node.js 20.x(包含 npm)。
-
在 GitHub 上创建一个新的公共仓库,并将其命名为“hello-world-javascript-action”。更多信息,请参阅“创建新的仓库”。
-
将你的仓库克隆到你的计算机。更多信息,请参阅“克隆仓库”。
-
在你的终端中,将目录更改为你的新仓库。
Shell cd hello-world-javascript-action
cd hello-world-javascript-action
-
在你的终端中,使用 npm 初始化目录以生成一个
package.json
文件。Shell npm init -y
npm init -y
创建 action 元数据文件
在hello-world-javascript-action
目录中创建一个名为action.yml
的新文件,其中包含以下示例代码。更多信息,请参阅“GitHub Actions 的元数据语法”。
name: 'Hello World' description: 'Greet someone and record the time' 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: 'node20' main: 'index.js'
name: 'Hello World'
description: 'Greet someone and record the time'
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: 'node20'
main: 'index.js'
此文件定义了who-to-greet
输入和time
输出。它还告诉 action runner 如何开始运行此 JavaScript action。
添加 actions 工具包软件包
actions 工具包是一组 Node.js 软件包,允许你更快地构建更一致的 JavaScript actions。
工具包@actions/core
软件包提供了一个与工作流程命令、输入和输出变量、退出状态以及调试消息交互的接口。
工具包还提供了一个@actions/github
软件包,它返回一个经过身份验证的 Octokit REST 客户端以及对 GitHub Actions 上下文的访问权限。
工具包提供的软件包不仅仅是core
和github
。更多信息,请参阅actions/toolkit仓库。
在你的终端中,安装 actions 工具包的core
和github
软件包。
npm install @actions/core npm install @actions/github
npm install @actions/core
npm install @actions/github
现在你应该会看到一个包含你刚刚安装的模块的node_modules
目录,以及一个包含已安装模块依赖项及其版本的package-lock.json
文件。
编写 action 代码
此 action 使用工具包获取 action 元数据文件中所需的who-to-greet
输入变量,并在日志的调试消息中打印“Hello [who-to-greet]”。接下来,脚本获取当前时间并将其设置为输出变量,以便作业中稍后运行的 actions 可以使用。
GitHub Actions 提供有关 webhook 事件、Git refs、工作流程、action 以及触发工作流程的人员的上下文信息。要访问上下文信息,可以使用github
软件包。你将编写的 action 会将 webhook 事件有效负载打印到日志中。
添加一个名为index.js
的新文件,其中包含以下代码。
const core = require('@actions/core'); const github = require('@actions/github'); try { // `who-to-greet` input defined in action metadata file const nameToGreet = core.getInput('who-to-greet'); console.log(`Hello ${nameToGreet}!`); const time = (new Date()).toTimeString(); core.setOutput("time", time); // Get the JSON webhook payload for the event that triggered the workflow const payload = JSON.stringify(github.context.payload, undefined, 2) console.log(`The event payload: ${payload}`); } catch (error) { core.setFailed(error.message); }
const core = require('@actions/core');
const github = require('@actions/github');
try {
// `who-to-greet` input defined in action metadata file
const nameToGreet = core.getInput('who-to-greet');
console.log(`Hello ${nameToGreet}!`);
const time = (new Date()).toTimeString();
core.setOutput("time", time);
// Get the JSON webhook payload for the event that triggered the workflow
const payload = JSON.stringify(github.context.payload, undefined, 2)
console.log(`The event payload: ${payload}`);
} catch (error) {
core.setFailed(error.message);
}
如果在上面的index.js
示例中抛出错误,core.setFailed(error.message);
将使用 actions 工具包@actions/core
软件包来记录消息并设置失败的退出代码。更多信息,请参阅“设置 actions 的退出代码”。
创建 README
为了让人们知道如何使用你的 action,你可以创建一个 README 文件。当你计划公开共享你的 action 时,README 最有用,但它也是提醒你或你的团队如何使用 action 的好方法。
在你的hello-world-javascript-action
目录中,创建一个README.md
文件,其中指定以下信息:
- 对 action 功能的详细描述。
- 必需的输入和输出参数。
- 可选的输入和输出参数。
- action 使用的密钥。
- action 使用的环境变量。
- 如何在工作流程中使用你的 action 的示例。
# Hello world javascript action This action prints "Hello World" or "Hello" + the name of a person to greet to the log. ## Inputs ### `who-to-greet` **Required** The name of the person to greet. Default `"World"`. ## Outputs ### `time` The time we greeted you. ## Example usage ```yaml uses: actions/hello-world-javascript-action@e76147da8e5c81eaf017dede5645551d4b94427b with: who-to-greet: 'Mona the Octocat' ```
# Hello world javascript action
This action prints "Hello World" or "Hello" + the name of a person to greet to the log.
## Inputs
### `who-to-greet`
**Required** The name of the person to greet. Default `"World"`.
## Outputs
### `time`
The time we greeted you.
## Example usage
```yaml
uses: actions/hello-world-javascript-action@e76147da8e5c81eaf017dede5645551d4b94427b
with:
who-to-greet: 'Mona the Octocat'
```
提交、标记和推送你的 action 到 GitHub
GitHub 在运行时下载工作流程中每次 action 运行,并在你可以使用run
等工作流程命令与 runner 机器交互之前将其作为完整的代码包执行。这意味着你必须包含运行 JavaScript 代码所需的任何软件包依赖项。你需要将工具包core
和github
软件包检入你的 action 的仓库。
在你的终端中,提交你的action.yml
、index.js
、node_modules
、package.json
、package-lock.json
和README.md
文件。如果你添加了一个列出node_modules
的.gitignore
文件,则需要删除该行才能提交node_modules
目录。
最好也为你的 action 的版本添加版本标记。有关你的 action 版本控制的更多信息,请参阅“关于自定义 actions”。
git add action.yml index.js node_modules/* package.json package-lock.json README.md git commit -m "My first action is ready" git tag -a -m "My first action release" v1.1 git push --follow-tags
git add action.yml index.js node_modules/* package.json package-lock.json README.md
git commit -m "My first action is ready"
git tag -a -m "My first action release" v1.1
git push --follow-tags
检入你的node_modules
目录可能会导致问题。作为替代方案,你可以使用名为@vercel/ncc
的工具来编译你的代码和模块到一个用于分发的文件中。
-
通过在你的终端中运行此命令来安装
vercel/ncc
。npm i -g @vercel/ncc
-
编译你的
index.js
文件。ncc build index.js --license licenses.txt
你将看到一个新的
dist/index.js
文件,其中包含你的代码和已编译的模块。你还会看到一个相应的dist/licenses.txt
文件,其中包含你正在使用的node_modules
的所有许可证。 -
更改你的
action.yml
文件中的main
关键字以使用新的dist/index.js
文件。main: 'dist/index.js'
-
如果你已经检入你的
node_modules
目录,请将其删除。rm -rf node_modules/*
-
在你的终端中,提交对你的
action.yml
、dist/index.js
和node_modules
文件的更新。Shell git add action.yml dist/index.js node_modules/* git commit -m "Use vercel/ncc" git tag -a -m "My first action release" v1.1 git push --follow-tags
git add action.yml dist/index.js node_modules/* git commit -m "Use vercel/ncc" git tag -a -m "My first action release" v1.1 git push --follow-tags
在工作流程中测试你的 action
现在你可以准备在工作流程中测试你的 action 了。
公共 action 可被任何仓库中的工作流程使用。当 action 位于私有仓库中时,仓库设置决定 action 是否仅在同一仓库中可用,或者也对同一用户或组织拥有的其他仓库可用。更多信息,请参阅“管理仓库的 GitHub Actions 设置”。
使用公共 action 的示例
此示例演示了如何从外部仓库中运行你的新的公共 action。
将以下 YAML 复制到.github/workflows/main.yml
中的新文件中,并使用你的用户名和你在上面创建的公共仓库的名称更新uses: octocat/hello-world-javascript-action@1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b
行。你也可以将who-to-greet
输入替换为你的姓名。
on: [push] jobs: hello_world_job: runs-on: ubuntu-latest name: A job to say hello steps: - name: Hello world action step id: hello uses: octocat/hello-world-javascript-action@1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b with: who-to-greet: 'Mona the Octocat' # Use the output from the `hello` step - name: Get the output time run: echo "The time was ${{ steps.hello.outputs.time }}"
on: [push]
jobs:
hello_world_job:
runs-on: ubuntu-latest
name: A job to say hello
steps:
- name: Hello world action step
id: hello
uses: octocat/hello-world-javascript-action@1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b
with:
who-to-greet: 'Mona the Octocat'
# Use the output from the `hello` step
- name: Get the output time
run: echo "The time was ${{ steps.hello.outputs.time }}"
触发此工作流程时,runner 将从你的公共仓库下载hello-world-javascript-action
action,然后执行它。
使用私有 action 的示例
将工作流程代码复制到 action 仓库中的.github/workflows/main.yml
文件中。你也可以将who-to-greet
输入替换为你的姓名。
.github/workflows/main.yml
on: [push] jobs: hello_world_job: runs-on: ubuntu-latest name: A job to say hello steps: # To use this repository's private action, # you must check out the repository - name: Checkout uses: actions/checkout@v4 - name: Hello world action step uses: ./ # Uses an action in the root directory id: hello with: who-to-greet: 'Mona the Octocat' # Use the output from the `hello` step - name: Get the output time run: echo "The time was ${{ steps.hello.outputs.time }}"
on: [push]
jobs:
hello_world_job:
runs-on: ubuntu-latest
name: A job to say hello
steps:
# To use this repository's private action,
# you must check out the repository
- name: Checkout
uses: actions/checkout@v4
- name: Hello world action step
uses: ./ # Uses an action in the root directory
id: hello
with:
who-to-greet: 'Mona the Octocat'
# Use the output from the `hello` step
- name: Get the output time
run: echo "The time was ${{ steps.hello.outputs.time }}"
在你的仓库中,点击**Actions**选项卡,然后选择最新的工作流程运行。在**Jobs**下或可视化图表中,点击**A job to say hello**。
点击**Hello world action step**,你应该会看到日志中打印了“Hello Mona the Octocat”或你用于who-to-greet
输入的名称。要查看时间戳,请点击**Get the output time**。
用于创建 JavaScript actions 的模板仓库
GitHub 提供用于创建 JavaScript 和 TypeScript actions 的模板仓库。你可以使用这些模板快速开始创建包含测试、整理和其他推荐实践的新 action。
GitHub.com 上的 JavaScript actions 示例
你可以在 GitHub.com 上找到许多 JavaScript actions 的示例。