在本指南中,你将了解创建和使用打包的 JavaScript 操作所需的基本组件。为了将本指南重点放在打包操作所需的组件上,操作代码的功能是最小的。该操作在日志中打印“Hello World”,如果你提供自定义名称,则打印“Hello [who-to-greet]”。
本指南使用 GitHub Actions Toolkit Node.js 模块来加快开发速度。有关更多信息,请参阅 actions/toolkit 存储库。
完成此项目后,你应该了解如何构建自己的 JavaScript 操作并在工作流中对其进行测试。
为了确保你的 JavaScript 操作与所有 GitHub 托管的运行器(Ubuntu、Windows 和 macOS)兼容,你编写的打包 JavaScript 代码应为纯 JavaScript,而不依赖于其他二进制文件。JavaScript 操作直接在运行器上运行,并使用运行器映像中已存在的二进制文件。
警告:在创建工作流和操作时,你应始终考虑你的代码是否可能执行来自潜在攻击者的不受信任的输入。某些上下文应被视为不受信任的输入,因为攻击者可以插入自己的恶意内容。有关更多信息,请参阅“GitHub Actions 的安全强化”。
开始之前,你需要下载 Node.js 并创建一个公共 GitHub 存储库。
-
下载并安装 Node.js 20.x,其中包括 npm。
https://node.org.cn/en/download/
-
在 GitHub.com 上创建一个新的公共存储库,并将其命名为“hello-world-javascript-action”。有关更多信息,请参阅“创建新存储库”。
-
将存储库克隆到你的计算机。有关更多信息,请参阅“克隆存储库”。
-
在终端中,将目录更改为你的新存储库。
Shellcd hello-world-javascript-action
cd hello-world-javascript-action
-
在终端中,使用 npm 初始化目录以生成 package.json
文件。
在 hello-world-javascript-action
目录中创建一个名为 action.yml
的新文件,并使用以下示例代码。有关更多信息,请参阅“GitHub Actions 的元数据语法”。
YAMLname: '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:
description: 'Who to greet'
required: true
default: 'World'
outputs:
time:
description: 'The time we greeted you'
runs:
using: 'node20'
main: 'index.js'
此文件定义了 who-to-greet
输入和 time
输出。它还告诉操作运行器如何开始运行此 JavaScript 操作。
操作工具包是一组 Node.js 包,可让你使用更强的连贯性快速构建 JavaScript 操作。
工具包 @actions/core
包提供了一个界面,用于工作流命令、输入和输出变量、退出状态和调试消息。
该工具包还提供一个 @actions/github
包,该包返回一个经过身份验证的 Octokit REST 客户端,并可以访问 GitHub 操作上下文。
该工具包提供的不仅仅是 core
和 github
包。有关更多信息,请参阅 actions/toolkit 存储库。
在你的终端中,安装操作工具包 core
和 github
包。
Shellnpm install @actions/core
npm install @actions/github
npm install @actions/core
npm install @actions/github
现在你应该会看到一个 node_modules
目录,其中包含你刚刚安装的模块,以及一个 package-lock.json
文件,其中包含已安装模块的依赖项和每个已安装模块的版本。
此操作使用工具包来获取操作元数据文件中必需的 who-to-greet
输入变量,并在日志中以调试消息的形式打印“Hello [who-to-greet]”。接下来,该脚本获取当前时间,并将其设置为输出变量,以便稍后在作业中运行的操作可以使用该变量。
GitHub 操作提供有关 Webhook 事件、Git 引用、工作流、操作以及触发工作流的人员的上下文信息。要访问上下文信息,可以使用 github
包。你将编写的操作会将 Webhook 事件有效负载打印到日志中。
添加一个名为 index.js
的新文件,其中包含以下代码。
JavaScriptconst 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 {
const nameToGreet = core.getInput('who-to-greet');
console.log(`Hello ${nameToGreet}!`);
const time = (new Date()).toTimeString();
core.setOutput("time", time);
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/core
包来记录一条消息并设置一个失败的退出代码。有关更多信息,请参阅“为操作设置退出代码”。
为了让人们知道如何使用你的操作,你可以创建一个 README 文件。README 在你计划公开分享你的操作时最有帮助,但也是提醒你或你的团队如何使用该操作的好方法。
在 hello-world-javascript-action
目录中,创建一个 README.md
文件,指定以下信息
- 对操作执行的操作的详细说明。
- 必需的输入和输出参数。
- 可选的输入和输出参数。
- 操作使用的机密。
- 操作使用的环境变量。
- 在工作流中使用操作的示例。
Markdown# 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'
```
在运行时,GitHub 会下载工作流中运行的每个操作,并在可以使用 run
等工作流命令与运行器计算机进行交互之前,将其作为完整的代码包执行。这意味着你必须包括运行 JavaScript 代码所需的任何包依赖项。你需要将工具包 core
和 github
包签入操作存储库。
从你的终端提交 action.yml
、index.js
、node_modules
、package.json
、package-lock.json
和 README.md
文件。如果你添加了一个列出 node_modules
的 .gitignore
文件,则需要删除该行以提交 node_modules
目录。
最佳做法还包括为操作版本添加版本标记。有关对操作进行版本控制的更多信息,请参阅“关于自定义操作”。
Shellgit 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
文件的更新。
Shellgit 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
现在,您已准备好在一个工作流中测试您的操作。
任何存储库中的工作流都可以使用公共操作。当操作位于私有存储库中时,存储库设置决定操作是仅在同一存储库中可用,还是对同一用户或组织拥有的其他存储库也可用。有关详细信息,请参阅“管理存储库的 GitHub Actions 设置”。
此示例演示如何从外部存储库运行您的新公共操作。
将以下 YAML 复制到 .github/workflows/main.yml
中的新文件中,并使用您的用户名和上面创建的公共存储库的名称更新 uses: octocat/[email protected]
行。您还可以使用您的姓名替换 who-to-greet
输入。
YAMLon: [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/[email protected]
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/[email protected]
with:
who-to-greet: 'Mona the Octocat'
- name: Get the output time
run: echo "The time was ${{ steps.hello.outputs.time }}"
触发此工作流后,运行器将从您的公共存储库下载 hello-world-javascript-action
操作,然后执行该操作。
将工作流代码复制到操作存储库中的 .github/workflows/main.yml
文件中。您还可以使用您的姓名替换 who-to-greet
输入。
.github/workflows/main.yml
YAMLon: [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:
- name: Checkout
uses: actions/checkout@v4
- name: Hello world action step
uses: ./
id: hello
with:
who-to-greet: 'Mona the Octocat'
- name: Get the output time
run: echo "The time was ${{ steps.hello.outputs.time }}"
在您的存储库中,单击“操作”选项卡,然后选择最新的工作流运行。在“作业”下或在可视化图表中,单击“问候作业”。
单击“Hello world 操作步骤”,您应该会看到日志中打印的“Hello Mona the Octocat”或您用于 who-to-greet
输入的名称。要查看时间戳,请单击“获取输出时间”。
GitHub 提供了用于创建 JavaScript 和 TypeScript 操作的模板存储库。您可以使用这些模板快速开始创建包含测试、linting 和其他推荐做法的新操作。
您可以在 GitHub.com 上找到许多 JavaScript 操作示例。